„dropDups“ синтаксисът за създаване на индекс е "оттеглен" от MongoDB 2.6 и премахнат в MongoDB 3.0. В повечето случаи не е много добра идея да използвате това, тъй като "премахването" е произволно и всеки "дубликат" може да бъде премахнат. Което означава, че това, което се „премахва“, може да не е това, което наистина искате да премахнете.
Така или иначе се сблъсквате с грешка "дължина на индекса", тъй като стойността на индексния ключ тук би била по-дълга, отколкото е позволено. Най-общо казано, вие не сте "предназначени" да индексирате 43 полета във всяко нормално приложение.
Ако искате да премахнете „дубликатите“ от колекция, най-добрият ви залог е да изпълните заявка за обобщаване, за да определите кои документи съдържат „дубликати“ данни и след това да преминете през този списък, като премахнете „всички освен един“ от вече „уникалните“ _id
стойности от целевата колекция. Това може да се направи с "насипни" операции за максимална ефективност.
ЗАБЕЛЕЖКА :Трудно ми е да повярвам, че вашите документи всъщност съдържат 43 "уникални" полета. Вероятно е „всичко, от което се нуждаете“ е просто да се идентифициратсамо тези полета, които правят документа "уникален" и след това следвайте процеса, както е описано по-долу:
var bulk = db.testkdd.initializeOrderedBulkOp(),
count = 0;
// List "all" fields that make a document "unique" in the `_id`
// I am only listing some for example purposes to follow
db.testkdd.aggregate([
{ "$group": {
"_id": {
"duration" : "$duration",
"protocol_type": "$protocol_type",
"service": "$service",
"flag": "$flag"
},
"ids": { "$push": "$_id" },
"count": { "$sum": 1 }
}},
{ "$match": { "count": { "$gt": 1 } } }
],{ "allowDiskUse": true}).forEach(function(doc) {
doc.ids.shift(); // remove first match
bulk.find({ "_id": { "$in": doc.ids } }).remove(); // removes all $in list
count++;
// Execute 1 in 1000 and re-init
if ( count % 1000 == 0 ) {
bulk.execute();
bulk = db.testkdd.initializeOrderedBulkOp();
}
});
if ( count % 1000 != 0 )
bulk.execute();
Ако имате версия на MongoDB "по-ниска" от 2.6 и нямате групови операции, тогава можете да опитате със стандартен .remove()
и вътре в цикъла. Също така отбелязваме, че .aggregate()
няма да върне курсор тук и цикълът трябва да се промени на:
db.testkdd.aggregate([
// pipeline as above
]).result.forEach(function(doc) {
doc.ids.shift();
db.testkdd.remove({ "_id": { "$in": doc.ids } });
});
Но не забравяйте да разгледате внимателно документите си и да включите само „само“ „уникалните“ полета, които очаквате да бъдат част от групирането _id
. В противен случай в крайна сметка не премахвате нищо, тъй като там няма дубликати.