2014-10-24 14 views
17

Ich muss überprüfen, ob eine find-Anweisung eine nicht leere Abfrage zurückgibt.Wie überprüft man, ob ein Pymongo-Cursor Abfrageergebnisse hat

Was war ich tat folgendes:

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

Dann wurde mir klar, dass meine if Anweisung nie ausgeführt wurde, weil find einen Cursor zurückgibt, entweder die Abfrage leer ist oder nicht.

Deshalb überprüfte ich die documentation und ich finde zwei Methoden, die mir helfen können:

  1. count(with_limit_and_skip=False), die (aus der Beschreibung):

    die Anzahl der Dokumente in den Ergebnissen Kosten festgelegt für diese Abfrage.

    Es scheint ein guter Weg, um zu überprüfen, aber das bedeutet, dass ich alle Ergebnisse in Cursor zählen müssen wissen, ob es Null ist oder nicht, nicht wahr? Ein bisschen teuer?

  2. retrieved, die (aus der Beschreibung):

    Die Anzahl der Dokumente bisher abgerufen.

    ich es auf einem leeren Abfragesatz getestet und es gibt Null zurück, aber es ist nicht klar, was es tut, und ich weiß nicht, ob es das Richtige für mich ist.

Also, was ist der beste Weg (best practice) zu überprüfen, ob eine find() Abfrage eine leere Menge oder nicht zurückkehrt? Ist eine der oben beschriebenen Methoden zu diesem Zweck richtig? Und was ist mit Leistung? Gibt es andere Möglichkeiten, es zu tun?


Nur um klar zu sein: Ich muß, wenn die Abfrage leer wissen ist, und ich mag den besten Weg, mit dem Cursor in Bezug auf Leistung finden und pythonic zu sein.

+0

Das hängt davon ab, was Sie mit ihm tun möchte –

+0

@VincentBeltman ich gerade brauchen zu wissen, ob die Abfrage mit diesem Cursor etwas zurückgibt. – boh

+0

Sie führen die Abfrage ohnehin in Ihrer collection.find() -Methode durch. Die "count" -Methode gibt nur die Anzahl der Dokumente zurück, die die find-Methode an den Cursor zurückgegeben hat. Sie würden nur tun "wenn query.count> 0:" – vintastic

Antwort

22

.count() ist der richtige Weg, um die Anzahl der Ergebnisse zu finden, die in der Abfrage zurückgegeben werden. Die count() Methode erschöpft nicht den Iterator für Ihren Cursor, so dass Sie sicher eine .count() Prüfung durchführen können, bevor Sie über die Elemente in der Ergebnismenge iterieren.

Die Leistung der Zählmethode wurde in MongoDB 2.4 erheblich verbessert. Die einzige Sache, die Ihre count verlangsamen könnte, ist, ob die Abfrage einen Index darauf gesetzt hat oder nicht. Um herauszufinden, ob Sie einen Index für die Abfrage haben, können Sie so etwas wie

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

tun Wenn Sie BasicCursor im Ergebnis zu sehen, müssen Sie einen Index für Ihre string Feld für diese Abfrage.

+0

Vielen Dank, dass Sie diesen Mate heraufbringen. .count() ist die perfekte Funktion, um nicht leere Abfragen zu überprüfen. Ich hatte ähnliches Problem und wurde mit dieser Funktion gelöst. –

7

Wie wäre es mit nur find_one statt find? Dann können Sie einfach überprüfen, ob Sie ein Ergebnis oder None erhalten haben.Und wenn "string" indiziert ist, können Sie fields = {"string":1, "_id" :0} übergeben und somit eine Nur-Index-Abfrage erstellen, die noch schneller ist.

+0

Das Feld 'string' ist indiziert, aber ich kann' findOne' nicht verwenden, weil nicht garantiert ist, dass es nur ein Ergebnis gibt (es ist tatsächlich unwahrscheinlich, dass es ein solches gibt). – boh

+2

In meinem Verständnis ist alles, was Sie wissen wollen, ob Sie irgendwelche Ergebnisse für die Abfrage haben oder nicht, ist das korrekt? Wenn dies der Fall ist, ist find_one genug für Ihren Fall: Wenn es einen Wert zurückgibt, bedeutet dies, dass find() mindestens ein Ergebnis gefunden hätte, und wenn es 'None' zurückgibt, würde find() 0 Ergebnisse zurückgeben . –

+0

Ja, aber wenn es keine Ergebnisse gibt, werde ich etwas tun, sonst werde ich etwas mit Ergebnissen tun, die alle von ihnen zeigen. Sagen Sie, dass es effizienter ist, eine Abfrage mit 'findOne' auf einem indizierten Feld durchzuführen, und wenn es nicht leer ist, führen Sie die Abfrage erneut mit' find' durch? – boh

2

Von meinen Tests ist der schnellste Weg

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 

(Verwenden von MongoDB 2.6.7, 2015.03.26)

Verwandte Themen