python - collection - Cómo comprobar si un cursor pymongo tiene resultados de consulta
mongoose count (4)
¿Qué tal solo usando find_one
lugar de find
? Luego puedes verificar si obtuviste un resultado o None
. Y si la "cadena" está indexada, puede pasar fields = {"string":1, "_id" :0}
, y así convertirla en una consulta de solo índice, que es aún más rápida.
Necesito verificar si una declaración de find
devuelve una consulta no vacía.
Lo que estaba haciendo era lo siguiente:
query = collection.find({"string": field})
if not query: #do something
Entonces me di cuenta de que mi sentencia if
nunca se ejecutó porque find
devuelve un cursor, ya sea que la consulta esté vacía o no.
Por lo tanto, revisé la documentation y encontré dos métodos que me pueden ayudar:
count(with_limit_and_skip=False)
que (de la descripción):Devuelve el número de documentos en el conjunto de resultados para esta consulta.
Parece una buena forma de comprobarlo, pero esto significa que necesito contar todos los resultados en el cursor para saber si es cero o no, ¿verdad? Un poco caro?
retrieved
que (de la descripción):El número de documentos recuperados hasta el momento.
Lo probé en un conjunto de consultas vacío y devuelve cero, pero no está claro lo que hace y no sé si es lo correcto para mí.
Entonces, ¿cuál es la mejor manera (mejor práctica) de verificar si una consulta find()
devuelve un conjunto vacío o no? ¿Es uno de los métodos descritos anteriormente adecuado para este propósito? ¿Y qué pasa con el rendimiento? ¿Hay otras formas de hacerlo?
Solo para ser claros: necesito saber si la consulta está vacía y me gustaría encontrar la mejor manera con el cursor con respecto al rendimiento y al ser pythonic.
De mis pruebas, la forma más rápida es
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
(Utilizando MongoDB 2.6.7, 2015-03-26)
Otra solución es convertir el cursor en lista, si el cursor no tiene ningún dato, la lista vacía de else si contiene todos los datos.
doc_list = collection.find({}); #find all data
have_list = True if len(list(doc_list)) else False;
EDITAR : Si bien esto fue cierto en 2014, las versiones modernas de pymongo y MongoDB han cambiado este comportamiento. El comprador tenga cuidado:
.count()
es la forma correcta de encontrar el número de resultados que se devuelven en la consulta. El método count()
no agota el iterador de su cursor, por lo que puede hacer una comprobación de .count()
manera segura antes de iterar sobre los elementos del conjunto de resultados.
El rendimiento del método de conteo mejoró enormemente en MongoDB 2.4. Lo único que podría ralentizar el count
es si la consulta tiene un índice establecido o no. Para saber si tiene un índice en la consulta, puede hacer algo como
query = collection.find({"string": field})
print query.explain()
Si ve BasicCursor
en el resultado, necesita un índice en el campo de string
para esta consulta.
EDITAR : como señaló @alvapan, pymongo desaprobó este método en pymongo 3.7+ y ahora prefiere que use count_documents
en una consulta separada.
item_count = collection.count_documents({"string": field})
La forma correcta de contar el número de elementos que ha devuelto en una consulta es verificar el contador .retreived
en la consulta después de .retreived
, o enumerate
la consulta en primer lugar:
# Using .retrieved
query = collection.find({"string": field})
for item in query:
print(item)
print(''Located {0:,} item(s)''.format(query.retrieved))
O, de otra manera:
# 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))