Как я могу удалить дубликаты в MongoDb? - PullRequest
5 голосов
/ 18 февраля 2012

У меня есть большая коллекция (~ 2,7 миллиона документов) в mongodb, и там много дубликатов.Я попытался запустить ensureIndex({id:1}, {unique:true, dropDups:true}) в коллекции.Монго отмахивается от него некоторое время, прежде чем решает, что too many dups on index build with dropDups=true.

Как мне добавить индекс и избавиться от дубликатов?Или наоборот, каков наилучший способ удаления некоторых дупов, чтобы монго могло успешно построить индекс?

Для бонусных баллов, почему существует ограничение на количество дупсов, которые можно сбросить?

Ответы [ 2 ]

5 голосов
/ 18 февраля 2012

Для бонусных баллов, почему существует ограничение на количество сбросов, которое можно сбросить?

MongoDB, вероятно, делает это, чтобы защитить себя. Если вы введете dropDups в неправильное поле, вы можете объединить весь набор данных и заблокировать БД с помощью операций удаления (которые «столь же дороги», как и записи).

Как добавить индекс и избавиться от дубликатов?

Итак, первый вопрос: почему вы создаете уникальный индекс в поле id?

MongoDB создает поле _id по умолчанию, которое автоматически уникально индексируется и . По умолчанию MongoDB заполняет _id ObjectId, однако вы можете переопределить это любым значением, которое вам нравится. Так что, если у вас есть готовый набор значений ID, вы можете использовать эти .

Если вы не можете повторно импортировать значения, скопируйте их в новую коллекцию, изменив id на _id. Затем вы можете удалить старую коллекцию и переименовать новую. ( обратите внимание, что вы получите кучу «ошибок повторяющихся ключей», убедитесь, что ваш код перехватывает и игнорирует их )

3 голосов
/ 13 июня 2013

Я столкнулся с этим вопросом, пытаясь найти обходной путь для проблемы «слишком много дуплей» (без повторного создания коллекции из источника). В конце концов, я сделал это, создав новую коллекцию c2, добавив уникальный индекс в нужное поле (я) (исключительно для ускорения) и затем выполнив команду upsert:

db.c1.find().forEach(function(x){db.c2.update({field1:x.field1, field2:x.field2}, x, {upsert:true})})

, где комбинации field1 и field2 должны быть уникальными. Затем можно просто удалить начальную коллекцию c1 и переименовать новую. Это решение, как показано, может работать для одного или нескольких полей.

...