2015-05-12 12 views
15

W dokumentacji mongoDB jest napisane: "Zmieniono w wersji 3.0: opcja dropDups nie jest już dostępna."Mongo 3 duplikaty na unikalnym indeksie - dropDups

Czy jest coś, co mogę zrobić (poza obniżeniem klasyfikacji), jeśli chcę utworzyć niepowtarzalny indeks i niszczyć zduplikowane wpisy?

Należy pamiętać, że otrzymuję około 300 przekładek na sekundę, więc nie mogę po prostu usunąć wszystkich duplikatów i mam nadzieję, że żaden nie pojawi się przed zakończeniem indeksowania.

+0

Nie rozumiem twojego pytania. Czy mam rację, że masz już istniejące dokumenty, w tym duplikaty, a teraz chcesz umieścić unikalny indeks w polu, kontaktując się z duplikatami, a jednocześnie pojawiają się potencjalne nowe oszustwa? –

+1

tak. Chcę pozbyć się dupków i jeśli pojawią się nowe, odrzuć je. – Alonzorz

+0

Utknąłem również z tym problemem, czy jest jakakolwiek alternatywa, jak pozbyć się duplikatów bez 'dropDups' w MongoDB> = 3. * ?? –

Odpowiedz

11

Tak dropDupes jest teraz deprecated od wersji 2.7.5, ponieważ nie można było poprawnie przewidzieć, który dokument zostanie usunięty w procesie.

Zazwyczaj masz 2 opcje:

  1. użyć nowej kolekcji:

    • Utwórz nową kolekcję,
    • stworzyć unikalny indeks na tej nowej kolekcji,
    • Run wsad do kopiowania wszystkich dokumentów ze starej kolekcji do nowej i upewnij się, że zignorowałeś zduplikowany kluczowy błąd podczas procesu.
  2. sobie z nim we własnej kolekcji ręcznie:

    • upewnij się, że nie będzie więcej duplikatów dokumentów wstawić w kodzie,
    • prowadzony partię na swojej kolekcji, aby usunąć duplikaty (i upewnij się, że zachowujesz dobre, jeśli nie są całkowicie identyczne),
    • następnie dodaj unikalny indeks.

dla konkretnego przypadku, polecam pierwszą opcję ale trick:

  • Utwórz nową kolekcję o unikalnym indeksie
  • Aktualizacja kodu Więc teraz wstaw dokumenty w tabelach zarówno,
  • Uruchom wsadę, aby skopiować wszystkie dokumenty ze starej kolekcji na nową (zignoruj ​​d klucz uplication),
  • zmienić nazwę nowej kolekcji, aby pasowała do starej nazwy.
  • ponownie aktualizować swój kod, więc teraz tylko napisać w „starej” kolekcji
+1

Opcja 1 jest prawdopodobnie najlepszym sposobem na odtworzenie indeksów, ponieważ system live musi czekać na odbudowę indeksów, co może spowolnić działanie. – Pykler

+0

'upewnij się, że ignorujesz zduplikowany błąd klucza podczas procesu." Jak byś to zrobił? Wygląda na to, że błędy zatrzymują transakcję w połowie procesu. – Quest

+1

Użyj nieuporządkowanych insertów zbiorczych MongoDB: "Jeśli wystąpi błąd podczas przetwarzania jednej z operacji zapisu, MongoDB będzie kontynuować przetwarzanie pozostałych operacji zapisu na liście." Przykład: db.persons.insert ([{"_ id": "Bob"}, {"_id": "John"}, {"_id": "Bob"}, {"_id": "Marc"}] , {ordered: false}) wstawi 3 dokumenty i wyświetli jeden zduplikowany błąd klucza. Z {ordered: true}, tylko pierwsze 2 zostaną wstawione. Więcej dokumentów [tutaj] (https://docs.mongodb.com/manual/reference/method/db.collection.initializeUnorderedBulkOp/#db.collection.initializeUnorderedBulkOp) –

6

Jak podkreślił @ Maxime-Beugnet można utworzyć skrypt wsadowy, aby usunąć duplikaty z kolekcji. Zawarłem poniższe podejście, które jest stosunkowo szybkie, jeśli liczba duplikatów jest niewielka w porównaniu do rozmiaru kolekcji.Dla celów demonstracyjnych ten skrypt de-powielać kolekcję stworzoną przez następujący skrypt:

db.numbers.drop() 

var counter = 0 
while (counter<=100000){ 
    db.numbers.save({"value":counter}) 
    db.numbers.save({"value":counter}) 
    if (counter % 2 ==0){ 
    db.numbers.save({"value":counter}) 
    } 
    counter = counter + 1; 
} 

można usunąć duplikaty z tej kolekcji pisząc zapytanie zbiorczą, która zwraca wszystkie rekordy z więcej niż jednego duplikatu.

var cur = db.numbers.aggregate([{ $group: { _id: { value: "$value" }, uniqueIds: { $addToSet: "$_id" }, count: { $sum: 1 } } }, { $match: { count: { $gt: 1 } } }]); 

Za pomocą kursora można następnie iteracyjne ciągu zduplikowanych rekordów i zaimplementować własną logikę biznesową, aby zdecydować, które z duplikatów usunąć. W przykładzie poniżej Ja po prostu utrzymując pierwsze wystąpienie:

while (cur.hasNext()) { 
    var doc = cur.next(); 
    var index = 1; 
    while (index < doc.uniqueIds.length) { 
     db.numbers.remove(doc.uniqueIds[index]); 
     index = index + 1; 
    } 
} 

Po usunięciu duplikatów można dodać unikatowy indeks:

db.numbers.createIndex({"value":1},{unique:true}) 
0

pip install mongo_remove_duplicate_indexes

najlepszym sposobem będzie być utworzyć skrypt Pythona lub w dowolnym preferowanym języku, iteruj kolekcję, utwórz nową kolekcję z unikalnym indeksem ustawionym na true z db.collectionname.createIndex ({'inde xname ": 1}, unique: true), i wstaw swoje dokumenty z poprzedniej kolekcji do nowej kolekcji, a ponieważ klucz chciałeś być inny lub duplikaty usunięte nie zostaną wstawione do nowej kolekcji i będziesz w stanie z łatwością obsługiwać ekscesę z wyjątkiem obsługa

sprawdź kod źródłowy pakietu dla przykładu

Powiązane problemy