Как проверить, имеет ли курсор 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)