collection python mongodb pymongo mongodb-query

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:

  1. 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?

  2. 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))