Comment vérifier si un curseur pymongo a des résultats de requête

je dois vérifier si un find l'instruction retourne une requête non vide.

ce que je faisais était le suivant:

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

Puis j'ai réalisé que mon if déclaration n'a jamais été exécuté parce que find retourne un curseur, soit la requête est vide ou pas.

donc j'ai coché le documentation et j'ai trouver deux méthodes qui peuvent m'aider:

  1. count(with_limit_and_skip=False) qui (à partir de la description):

    Retourne le nombre de documents dans l'ensemble des résultats pour cette requête.

    Il me semble un bon moyen de vérifier, mais cela signifie que j'ai besoin de compter tous les résultats de curseur pour savoir si c'est nul ou pas, non? Un peu cher?

  2. retrieved qui (à partir de la description):

    le nombre de documents récupérés à ce jour.

    je l'ai testé sur une requête vide et il retourne zéro, mais c'est pas clairement ce qu'il fait et je ne sais pas si c'est bon pour moi.

Alors, quelle est la meilleure façon (best practice) pour vérifier si un find() la requête renvoie un jeu vide ou non? Est l'une des méthodes décrites ci-dessus à droite à cette fin? Et que dire de la performance? Il existe d'autres moyens de le faire?


juste pour être clair: j'ai besoin de savoir si la requête est vide et je voudrais trouver le meilleur moyen avec le curseur en ce qui concerne la performance et être pythonic.

25
demandé sur boh 2014-10-24 18:18:15

4 réponses

EDIT: alors que cela était vrai en 2014, les versions modernes de pymongo et MongoDB ont changé ce comportement. Acheteur prendre garde:

.count() est la bonne façon de trouver le nombre de résultats retournés par la requête. count() la méthode n'épuise pas l'itérateur pour votre curseur, vous pouvez donc faire un .count() vérifier avant d'itérer les éléments dans le jeu de résultats.

la performance de la méthode de comptage a été amélioré en MongoDB 2.4. La seule chose qui pourrait ralentir votre count si la requête a un indice fixés sur elle, ou pas. Pour savoir si vous avez un indice sur la requête, vous pouvez faire quelque chose comme

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

Si vous voyez BasicCursor dans le résultat, vous avez besoin d'un indice sur votre string champ pour cette requête.


EDIT: comme @alvapan l'a fait remarquer, pymongo a déprécié ceci méthode en pymongo 3.7 + et préfère maintenant que vous utilisez count_documents dans une requête distincte.

item_count = collection.count_documents({"string": field})

La bonne façon de compter le nombre d'articles que vous avez retourné sur une requête est de vérifier l' .retreived compteur sur la requête une fois que vous parcourez, ou enumeratela requête en premier lieu:

# Using .retrieved
query = collection.find({"string": field})
for item in query:
    print(item)

print('Located {0:,} item(s)'.format(query.retrieved))

Ou, d'une autre façon:

# Using the built-in enumerate
query = collection.find({"string": field})
for index, item in enumerate(query):
    print(item)

print('Located {0:,} item(s)'.format(index+1))
29
répondu VooDooNOFX 2018-07-09 05:03:56

pourquoi ne pas simplement utiliser find_one au lieu de find? Ensuite, vous pouvez simplement vérifier si vous avez obtenu un résultat ou None. Et si "chaîne" est indexé, vous pouvez passer fields = {"string":1, "_id" :0}, et ainsi en faire une requête index-only, ce qui est encore plus rapide.

7
répondu Baruch Oxman 2014-12-04 08:09:42

une autre solution est de convertir le curseur en liste, si le curseur n'a pas de données alors la liste vide contient toutes les données.

 doc_list = collection.find({}); #find all data
 have_list = True if len(list(doc_list)) else False;
3
répondu Biplab Malakar 2018-05-31 10:39:16

D'après mes tests, le moyen le plus rapide est

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

(En Utilisant MongoDB 2.6.7, 2015-03-26)

2
répondu Arnaud Fouchet 2015-03-26 09:44:51