MongoDB/PyMongo: запрос нескольких критериев — неожиданные результаты

У меня есть коллекция, в которой некоторые объекты имеют ключ foo. Теперь я пытаюсь запросить все объекты, которые действительно имеют этот ключ, но не с конкретным значением bar. Для этого я использую следующий запрос:

collection.find({'foo': {'$exists': True}, 'foo': {'$ne': 'bar'}})

Я думал, что оба критерия связаны через логическое И. Однако я также получаю объекты, у которых нет ключа foo. Фактически, я получаю тот же результат, когда просто использую запрос

collection.find({'foo': {'$ne': 'bar'}})

С другой стороны, если я использую

collection.find({'foo': {'$exists': True}})

Я правильно получаю только объекты с foo, но явно все они, поэтому некоторые из них имеют значение bar.

Как мне сформулировать запрос, чтобы получить первоначальный результат? Существует ли порядок, в котором проверяются несколько критериев? Я явно указываю логическое И обоих критериев?


person Christian    schedule 10.05.2014    source источник
comment
Это отличный пример базового запроса pymongo. Хотелось бы, чтобы это появилось раньше, когда я погуглил pymongo, нашел примеры :-\. +1   -  person Mike S    schedule 25.08.2015
comment
Я не думаю, что нужны конкретные примеры для PyMongo, поскольку синтаксис практически такой же, как при использовании оболочки Mongo. Я думаю, что оболочка Mongo немного более щедра, когда речь идет о заключении в кавычки ключевых слов и имен полей (например, {$ne : 'bar'} должно работать так же, как {'$ne' : 'bar'}). Возможно, также может иметь значение заглавная буква, например, True.   -  person Christian    schedule 26.08.2015


Ответы (2)


Вы можете использовать $and для объединения нескольких условий:

collection.find({"$and": [{"foo": {'$ne': 'bar'}}, 
                          {"foo": {'$exists': True}}]})
person alecxe    schedule 10.05.2014
comment
Отлично, спасибо! Я просто подумал, что если у вас есть список критериев, AND — это неявно заданный способ их проверки. Большинство примеров, которые я нашел, сосредоточены только на $or, отсюда, возможно, мое неправильное представление. Но поддерживать произвольные сложные условия и $and, конечно, очень важно. - person Christian; 10.05.2014
comment
более короткая версия для общего использования {"$and": [{"key1": value1}, {"key2": value2}]} - person citynorman; 12.04.2019

Нет необходимости использовать $and, это тоже работает

db.collection.find({"foo":{"$ne":"bar", "$exists":true}})
person Andrei Beziazychnyi    schedule 10.05.2014
comment
Хорошо, спасибо! Итак, я думаю, у меня есть эта проблема, поскольку оба критерия относятся к одному и тому же ключу foo. Есть ли разница в производительности между обоими решениями? - person Christian; 10.05.2014
comment
использование $and вернет весь документ (скажем, он возвращает только один результат), тогда как запрос без $and вернет только идентификатор результирующего документа. - person Arthur Zennig; 18.05.2021