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.