Как проверить, имеет ли курсор pymongo результаты запроса

Мне нужно проверить, возвращает ли оператор find непустой запрос.

Что я делал, было следующее:

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

Тогда я понял, что мой оператор if никогда не выполнялся, потому что find возвращает курсор, либо запрос пуст, либо нет.

Поэтому я проверил документацию, и я нахожу два метода, которые могут мне помочь:

  • count(with_limit_and_skip=False), который (из описания):

    Возвращает количество документов в результатах, заданных для этого запроса.

    Кажется, хороший способ проверить, но это означает, что мне нужно подсчитать все результаты в курсоре, чтобы узнать, равна нулю или нет, не так ли? Немного дороже?

  • retrieved, который (из описания):

    Число документов, полученных до сих пор.

    Я тестировал его на пустой набор запросов, и он возвращает ноль, но он не ясно, что он делает, и я не знаю, правильно ли это для меня.

Итак, что лучший способ (лучшая практика) проверить, возвращает ли запрос find() пустой набор или нет? Для этого подходит один из способов, описанных выше? А как насчет производительности? Есть ли другие способы сделать это?


Просто чтобы быть ясным: мне нужно знать, является ли запрос пустым, и я бы хотел найти лучший способ с помощью курсора относительно производительности и быть pythonic.

Ответы

Ответ 1

.count() - это правильный способ найти количество результатов, возвращаемых в запросе. Метод count() не исчерпывает итератор для вашего курсора, поэтому вы можете безопасно выполнить проверку .count() перед повторением элементов в результирующем наборе.

Эффективность метода count значительно улучшилась в MongoDB 2.4. Единственное, что может замедлить ваш count, - это то, что запрос имеет индекс, установленный на нем, или нет. Чтобы узнать, есть ли у вас индекс в запросе, вы можете сделать что-то вроде

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

Если вы видите BasicCursor в результате, вам нужен индекс в поле string для этого запроса.

Ответ 2

Как использовать только find_one вместо find? Затем вы можете просто проверить, есть ли у вас результат или None. И если индексируется "строка", вы можете передать fields = {"string":1, "_id" :0} и, таким образом, сделать запрос только по индексу, что еще быстрее.

Ответ 3

Из моих тестов самый быстрый способ

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

(Использование MongoDB 2.6.7, 2015-03-26)