sql >> Databáze >  >> NoSQL >> MongoDB

Odstraňte duplikáty na mongodb

pokud jste připraveni jednoduše zahodit všechny ostatní duplikáty, pak v podstatě chcete .aggregate() za účelem shromažďování dokumentů se stejným RegisterNumber hodnotu a odstraňte všechny ostatní dokumenty kromě první shody.

MongoDB 3.0.x postrádá některé moderní pomocníky, ale základy, které .aggregate() vrátí kurzor pro velké sady výsledků procesu a přítomnost "hromadných operací" protože výkon zápisu stále existuje:

var bulk = db.collection.initializeOrderedBulkOp();
var count = 0;

db.collection.aggregate([
  // Group on unique value storing _id values to array and count 
  { "$group": {
    "_id": "$RegisterNumber",
    "ids": { "$push": "$_id" },
    "count": { "$sum": 1 }      
  }},
  // Only return things that matched more than once. i.e a duplicate
  { "$match": { "count": { "$gt": 1 } } }
]).forEach(function(doc) {
  var keep = doc.ids.shift();     // takes the first _id from the array

  bulk.find({ "_id": { "$in": doc.ids }}).remove(); // remove all remaining _id matches
  count++;

  if ( count % 500 == 0 ) {  // only actually write per 500 operations
      bulk.execute();
      bulk = db.collection.initializeOrderedBulkOp();  // re-init after execute
  }
});

// Clear any queued operations
if ( count % 500 != 0 )
    bulk.execute();

V modernějších vydáních ( 3.2 a vyšší ) je preferováno použití bulkWrite() namísto. Všimněte si, že se jedná o „klientskou knihovnu“, protože stejné „hromadné“ metody uvedené výše se ve skutečnosti nazývají „pod kapotou“:

var ops = [];

db.collection.aggregate([
  { "$group": {
    "_id": "$RegisterNumber",
    "ids": { "$push": "$id" },
    "count": { "$sum": 1 }      
  }},
  { "$match": { "count": { "$gt": 1 } } }
]).forEach( doc => {

  var keep = doc.ids.shift();

  ops = [
    ...ops,
    {
      "deleteMany": { "filter": { "_id": { "$in": doc.ids } } }
    }
  ];

  if (ops.length >= 500) {
    db.collection.bulkWrite(ops);
    ops = [];
  }
});

if (ops.length > 0)
  db.collection.bulkWrite(ops);

Takže $group stáhne vše dohromady pomocí $RegisterNumber hodnotu a shromáždí odpovídající dokument _id hodnoty do pole. Pomocí $sum .

Poté odfiltrujte všechny dokumenty, které měly pouze počet 1 protože to zjevně nejsou duplikáty.

Předáním do smyčky odstraníte první výskyt _id ve shromážděném seznamu pro klíč s .shift() , přičemž v poli zůstanou pouze další "duplikáty".

Ty jsou předány do operace „odstranit“ pomocí $in jako „seznam“ dokumentů, které se mají porovnat a odstranit.

Proces je obecně stejný, pokud potřebujete něco složitějšího, jako je sloučení detailů z jiných duplicitních dokumentů, jen možná budete potřebovat více péče, pokud uděláte něco jako převod velikosti písmen „jedinečného klíče“, a tedy skutečně nejprve odstraníte duplikáty. před zápisem změn do dokumentu, který má být upraven.

V každém případě agregace zvýrazní dokumenty, které jsou ve skutečnosti „duplikáty“. Zbývající logika zpracování je založena na tom, co skutečně chcete s těmito informacemi dělat, jakmile je identifikujete.




  1. Jak připojit nodeJS docker kontejner k mongoDB

  2. Co je chyba Mongoose Odeslání do ObjectId selhalo pro hodnotu XXX na cestě _id?

  3. MongoDb:jak vytvořit správný (složený) index pro data s mnoha prohledávatelnými poli

  4. Jak přejmenovat více klíčů v Redis