2014-10-24 8 views
17

Devo verificare se un'istruzione find restituisce una query non vuota.Come verificare se un cursore pymongo presenta risultati di query

Quello che stavo facendo era il seguente:

query = collection.find({"string": field}) 
if not query: #do something 

poi ho capito che la mia if dichiarazione è stata mai eseguita perché find restituisce un cursore, o la query è vuota o non.

Quindi ho controllato i documentation e trovo due metodi che mi può aiutare:

  1. count(with_limit_and_skip=False) che (dalla descrizione):

    Restituisce il numero di documenti nei risultati fissati per questa domanda

    Mi sembra un buon modo per controllare, ma questo significa che ho bisogno di contare tutti i risultati di cursore sapere se è pari a zero o no, giusto? Un po 'costoso?

  2. retrieved che (dalla descrizione):

    Il numero di documenti recuperati finora.

    ho testato su un insieme di query vuota e restituisce zero, ma non è chiaro ciò che fa e non so se è giusto per me.

Quindi, che è il modo migliore (best practice) per verificare se una query find() restituisce un insieme vuoto o no? Uno dei metodi sopra descritti è adatto a questo scopo? E per quanto riguarda le prestazioni? Ci sono altri modi per farlo?


Giusto per essere chiari: ho bisogno di sapere se la query è vuota e mi piacerebbe trovare il modo migliore con il cursore per quanto riguarda le prestazioni e di essere divinatorio.

+0

Questo dipende da ciò che si vuole fare con esso –

+0

@VincentBeltman ho solo bisogno per sapere se la query restituisce qualcosa usando quel cursore. – boh

+0

Stai già eseguendo la query nel metodo collection.find() in ogni caso. Il metodo "count" sta solo restituendo il numero di documenti che il metodo find ha restituito al cursore. Dovresti semplicemente "se query.count> 0:" – vintastic

risposta

22

.count() è il modo corretto per trovare il numero di risultati restituiti nella query. Il metodo count() non esaurisce l'iteratore per il cursore, quindi è possibile eseguire in modo sicuro un controllo .count() prima di iterare sugli elementi nel set di risultati.

Le prestazioni del metodo di conteggio sono state notevolmente migliorate in MongoDB 2.4. L'unica cosa che potrebbe rallentare il tuo count è che la query ha un indice impostato su di esso, o no. Per scoprire se si dispone di un indice sulla query, si può fare qualcosa di simile

query = collection.find({"string": field}) 
print query.explain() 

Se si vede BasicCursor nel risultato, è necessario un indice sul vostro string campo per questa query.

+0

Grazie per aver portato questo compagno. .count() è la funzione perfetta per controllare query non vuote. Stavo avendo un problema simile ed è stato risolto con questa funzione. –

7

Che ne dici di utilizzare solo find_one anziché find? Quindi puoi controllare se hai un risultato o None.E se "stringa" è indicizzata, è possibile passare fields = {"string":1, "_id" :0} e quindi renderla una query solo indice, che è ancora più veloce.

+0

Il campo 'stringa' è indicizzato, ma non posso usare' findOne' perché non è garantito che ci sia un solo risultato (in realtà è improbabile che ce ne sia uno). – boh

+2

Nella mia comprensione, tutto quello che vuoi sapere è se hai qualche risultato per la query o no, è corretto? Se questo è il caso, find_one è sufficiente per il tuo caso: se restituisce un valore, significa che find() avrebbe trovato almeno un risultato, e se restituisce "None" significa che find() restituisce 0 risultati . –

+0

Sì, ma se non ci sono risultati, farò qualcosa, altrimenti farò qualcosa con i risultati, mostrando tipicamente tutti loro. Dici che è più efficiente fare una query con 'findOne' su un campo indicizzato e se non è vuota, esegui nuovamente la query con' find'? – boh

2

Da mio test, il modo più rapido è

if query.first(): 
    # do something 

In [51]: %timeit query = MyMongoDoc.objects(); query.first() 
100 loops, best of 3: 2.12 ms per loop 

In [52]: %timeit query = MyMongoDoc.objects(); query.count() 
100 loops, best of 3: 4.28 ms per loop 

(Usando MongoDB 2.6.7, 2015/03/26)