2015-05-12 12 views
15

Nella documentazione per mongoDB si dice: "Modificato nella versione 3.0: l'opzione dropDups non è più disponibile."mongo 3 duplicati su indice univoco - dropDups

C'è qualcosa che posso fare (oltre al downgrade) se in realtà voglio creare un indice univoco e distruggere le voci duplicate?

Si prega di tenere presente che ricevo circa 300 inserti al secondo, quindi non posso semplicemente cancellare tutti i duplicati e spero che nessuno possa entrare nel momento in cui ho finito di indicizzare.

+0

Non capisco la tua domanda. Ho capito bene che hai documenti esistenti compresi i duplicati e ora vuoi mettere un indice unico sul campo contattando duplicati mentre allo stesso tempo entrano in gioco potenziali nuovi imbroglioni? –

+1

si. Voglio sbarazzarmi dei fanatici e se ne arrivano di nuovi li respingo. – Alonzorz

+0

Ho anche bloccato questo problema, c'è qualche alternativa su come eliminare i duplicati senza 'dropDups' in MongoDB> = 3. * ?? –

risposta

11

dropDupes è ora deprecated dalla versione 2.7.5 perché non è stato possibile prevedere correttamente quale documento sarebbe stato eliminato durante il processo.

In genere, si hanno 2 opzioni:

  1. utilizzare una nuova collezione:

    • Creare una nuova collezione,
    • Creare l'indice univoco su questa nuova collezione,
    • Run un batch per copiare tutti i documenti dalla vecchia raccolta alla nuova e assicurarsi di ignorare l'errore della chiave duplicata durante il processo.
  2. Deal con esso nella propria collezione manualmente:

    • assicuratevi di non inserire documenti più duplicati nel codice,
    • eseguire un batch sulla vostra collezione di eliminare i duplicati (e assicurati di mantenere quello buono se non sono completamente identici),
    • quindi aggiungi l'indice univoco.

Per il vostro caso particolare, consiglio la prima opzione ma con un trucco:

  • Creare una nuova collezione con indice univoco,
  • aggiornare il codice in modo da ora inserire documenti in entrambi tabelle,
  • Eseguire un batch per copiare tutti i documenti dalla vecchia raccolta alla nuova (ignorare d errore chiave uplicated),
  • rinomina la nuova raccolta in modo che corrisponda al vecchio nome.
  • ri-aggiornare il codice in modo che ora scrive solo nella "vecchia" collezione
+1

L'opzione 1 è probabilmente il modo migliore per ricreare gli indici, dal momento che un sistema attivo dovrà attendere la ricostruzione degli indici, che può rallentarlo. – Pykler

+0

'assicurati di ignorare l'errore della chiave duplicata durante il processo. Come lo faresti? Sembra che gli errori interrompano la transazione a metà processo – Quest

+1

Usa gli inserimenti di massa non ordinati MongoDB: "Se si verifica un errore durante l'elaborazione di una delle operazioni di scrittura, MongoDB continuerà a elaborare le restanti operazioni di scrittura nell'elenco." Esempio: db.persons.insert ([{"_ id": "Bob"}, {"_id": "John"}, {"_id": "Bob"}, {"_id": "Marc"}] , {ordered: false}) inserirà 3 documenti e mostrerà un errore chiave duplicato. Con {ordered: true}, solo i primi 2 verrebbero inseriti. Altro documento [qui] (https://docs.mongodb.com/manual/reference/method/db.collection.initializeUnorderedBulkOp/#db.collection.initializeUnorderedBulkOp) –

6

come evidenziato dalla @ Maxime-Beugnet è possibile creare uno script batch per rimuovere i duplicati da una raccolta. Ho incluso il mio approccio qui sotto che è relativamente veloce se il numero di duplicati è piccolo rispetto alla dimensione della collezione.A scopo dimostrativo questo script de-duplicare la collezione creata da seguente script:

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; 
} 

È possibile rimuovere i duplicati di questa collezione scrivendo una query di aggregazione che restituisce tutti i record con più di un duplicato.

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

Utilizzando il cursore è possibile scorrere i record duplicati e realizzare la propria logica di business per decidere quale dei duplicati per rimuovere. Nell'esempio che segue Sto semplicemente mantenendo la prima occorrenza:

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

Dopo la rimozione dei duplicati è possibile aggiungere un indice univoco:

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

pip install mongo_remove_duplicate_indexes

miglior modo sarà sia per creare uno script python o in qualsiasi lingua tu preferisca, iterare la collezione, creare una nuova collezione con un indice univoco impostato su true con db.collectionname.createIndex ({'inde xname ': 1}, unique: true) e inserisci i tuoi documenti dalla raccolta precedente alla nuova raccolta e poiché la chiave che vuoi essere distinta o i duplicati rimossi non verranno inseriti nella tua nuova raccolta e puoi gestire facilmente l'ecxeption con eccezioni gestione

controllare il codice sorgente del pacchetto per l'esempio

Problemi correlati