2012-02-17 15 views
5

Mam dużą kolekcję (~ 2,7 miliona dokumentów) w mongodb i jest wiele duplikatów. Próbowałem uruchomić ensureIndex({id:1}, {unique:true, dropDups:true}) w kolekcji. Mongo odkłada go na chwilę, zanim zdecyduje, że too many dups on index build with dropDups=true.Jak mogę usunąć duplikaty w MongoDb?

Jak dodać indeks i pozbyć się duplikatów? Lub na odwrót, jaki jest najlepszy sposób na usunięcie dupków, aby mongo mogło z powodzeniem zbudować indeks?

Jeśli chodzi o punkty bonusowe, dlaczego istnieje ograniczenie liczby duplikatów, które można upuścić?

+0

Jako opcja: uruchom mapę/zmniejsz liczbę zliczeń dla każdego "identyfikatora". Następnie przejdź ten zestaw wyników i dla każdego "identyfikatora" z duplikatami usuń wszystkie rekordy, ale najpierw. –

Odpowiedz

5

Dla punktów bonusowych, dlaczego istnieje ograniczenie liczby duplikatów, które można upuścić?

MongoDB prawdopodobnie robi to, aby się obronić. Jeśli w niewłaściwym polu znajduje się dropDups, można połączyć cały zestaw danych i zablokować DB z operacjami usuwania (które są "tak drogie" jak zapisy).

Jak mogę dodać indeks i pozbyć się duplikatów?

Pierwsze pytanie brzmi: dlaczego tworzysz unikatowy indeks na polu id?

MongoDB tworzy domyślne pole, które jest automatycznie unikatowe: i zindeksowane. Domyślnie MongoDB zapełnia _id za pomocą ObjectId, jednak można go przesłonić dowolną wartością. Więc jeśli masz gotowy zestaw wartości ID, możesz użyć tych.

Jeśli nie możesz ponownie zaimportować wartości, skopiuj je do nowej kolekcji, zmieniając id na _id. Następnie możesz upuścić starą kolekcję i zmienić nazwę nowej. (Zauważ, że dostaniesz pakiet "duplikatów kluczowych błędów", upewnij się, że twój kod przechwytuje i ignoruje je)

+2

Edytuj wymagane! Ze względu na zmiany w MongoDB> = 3. * –

3

Natknąłem się na to pytanie, próbując znaleźć obejście problemu "zbyt wielu dupków" (bez ponownego tworzenia kolekcji ze źródła). Sposób, w jaki w końcu zrobił to tworząc nową kolekcję c2, dodając unikalny indeks na polu (s) potrzebny (wyłącznie dla szybkości przeznaczenia), a następnie robi upsert:

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

gdzie kombinacje field1 i field2 powinny być unikatowe. Następnie można po prostu upuścić początkową kolekcję c1 i zmienić nazwę nowego. To rozwiązanie, jak pokazano, może działać dla jednego lub wielu pól.

Powiązane problemy