2012-04-04 27 views
12

Ho una query, che seleziona i documenti da rimuovere. In questo momento, li rimuovo manualmente, come questo (usando python):Come eliminare documenti per query in modo efficiente in mongo?

for id in mycoll.find(query, fields={}): 
    mycoll.remove(id) 

Questo non sembra essere molto efficiente. C'è un modo migliore?

EDIT

OK, devo delle scuse per dimenticare di citare i dettagli della query, perché è importante. Ecco il codice python completo:

def reduce_duplicates(mydb, max_group_size): 
    # 1. Count the group sizes 
    res = mydb.static.map_reduce(jstrMeasureGroupMap, jstrMeasureGroupReduce, 'filter_scratch', full_response = True) 
    # 2. For each entry from the filter scratch collection having count > max_group_size 
    deleteFindArgs = {'fields': {}, 'sort': [('test_date', ASCENDING)]} 
    for entry in mydb.filter_scratch.find({'value': {'$gt': max_group_size}}): 
    key = entry['_id'] 
    group_size = int(entry['value']) 
    # 2b. query the original collection by the entry key, order it by test_date ascending, limit to the group size minus max_group_size. 
    for id in mydb.static.find(key, limit = group_size - max_group_size, **deleteFindArgs): 
     mydb.static.remove(id) 
    return res['counts']['input'] 

Quindi, che cosa fa? Riduce il numero di chiavi duplicate al massimo a max_group_size per valore chiave, lasciando solo i record più recenti. Funziona così:

  1. MR i dati a coppie (key, count).
  2. iterare su tutte le coppie con count > max_group_size
  3. interrogare i dati da key, mentre smistamento crescente dal timestamp (il primo più vecchia) e limitando il risultato ai count - max_group_size record più vecchi
  4. eliminare ogni trovato record.

Come si può vedere, questo compie il compito di ridurre i duplicati al massimo N record più recenti. Quindi, gli ultimi due passaggi sono foreach-found-remove e questo è il dettaglio importante della mia domanda, che cambia tutto e dovevo essere più specifico a riguardo - mi spiace.

Ora, sul comando di rimozione della raccolta. Accetta la query, ma la mia include l'ordinamento e la limitazione. Posso farlo con rimuovere? Bene, ho provato:

mydb.static.find(key, limit = group_size - max_group_size, sort=[('test_date', ASCENDING)]) 

Questo tentativo fallisce miseramente. Inoltre, sembra di avvitare mongo.Observe:

C:\dev\poc\SDR>python FilterOoklaData.py 
bad offset:0 accessing file: /data/db/ookla.0 - consider repairing database 

Inutile dire, che l'approccio foreach-trovato-rimuovere funziona e produce i risultati attesi.

Ora, spero di aver fornito un contesto sufficiente e (si spera) abbia ripristinato il mio onore perduto.

risposta

9

è possibile rimuoverlo direttamente usando il linguaggio MongoDB scripting:

db.mycoll.remove({_id:'your_id_here'}); 
+0

Ho modificato il mio post. – mark

28

È possibile utilizzare una query per rimuovere tutti i documenti corrispondenti

var query = {name: 'John'}; 
db.collection.remove(query); 

essere cauti, però, se il numero dei documenti corrispondenti è alto , il tuo database potrebbe diventare meno reattivo. Si consiglia spesso di cancellare i documenti in blocchi più piccoli.

Diciamo che si dispone di 100k documenti da eliminare da una raccolta. È meglio eseguire 100 query che cancellano 1k documenti ciascuno di 1 query che elimina tutti i documenti 100k.

+0

Ho modificato il mio post. – mark

+0

'Diciamo che hai 100k documenti da eliminare da una collezione. È meglio eseguire 100 query che cancellano 1k documenti ciascuno di una query che cancella tutti i documenti da 100k. Come hai potuto ottenere questo? – Ezequiel

+1

@Ezequiel: si possono recuperare id di tutti i documenti da eliminare, quindi dividerli in gruppi di 1000 e inviare diversi comandi di cancellazione con l'operatore '$ in'. –

0

eseguire la query in cmd

db.users.remove ({ "_id": ObjectId ("5a5f1c472ce1070e11fde4af")});

Se si utilizza node.js scrivere questo codice

User.remove({ _id: req.body.id },, function(err){...}); 
Problemi correlati