13

I have a collection where some of the objects feature an key foo. I now try to query for all objects that indeed have this key but not with the specific value bar. For this I use the following query:

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

I thought that both criteria are connected via a logical AND. However, I get also objects that don't feature key foo. In fact, I get the same result when I just use the query

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

On the other hans, if I use

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

I correctly only get objects with foo but obvisouly all of them, so some of them have the value bar.

How do I have to formulate my query to achieve my initial result? Is there a kind of order in which multiple criteria are tested? Do I explicitly specify the logical AND of both criteria?

Christian
  • 3,239
  • 5
  • 38
  • 79
  • This is a great example of a basic pymongo query. I wish it came up earlier when I googled "pymongo find examples" :-\ . +1 – Mike S Aug 25 '15 at 20:48
  • I don't think there's need for specific examples for PyMongo since the syntax is essentially the same as when using the Mongo shell. I _think_ the Mongo shell is a bit more generous when it comes to having quotes around keywords and field names(e.g., `{$ne : 'bar'}` should work as well as `{'$ne' : 'bar'}`). Maybe the capitalization of, e.g., `True` might matter also. – Christian Aug 26 '15 at 09:55

2 Answers2

41

You can use $and to join multiple conditions:

collection.find({"$and": [{"foo": {'$ne': 'bar'}}, 
                          {"foo": {'$exists': True}}]})
alecxe
  • 462,703
  • 120
  • 1,088
  • 1,195
  • Perfect, thanks! I just thought that if you have a list of criteria, `AND` is the implicitly given way to test them. Most example I found focused only on `$or`, hence perhaps my misconception. But to support arbitrary complex conditions, and `$and` is of course very meaningful. – Christian May 10 '14 at 05:19
  • 4
    shorter version for general uses `{"$and": [{"key1": value1}, {"key2": value2}]}` – citynorman Apr 12 '19 at 01:18
20

No necessary to use $and, it also works

db.collection.find({"foo":{"$ne":"bar", "$exists":true}})
Andrei Beziazychnyi
  • 2,897
  • 2
  • 16
  • 11
  • Cool, thanks! So I guess I have this issue since both criterea refer to the same key `foo`. Is there any difference regarding the performance between both solutions? – Christian May 10 '14 at 06:16
  • making use of "$and" will return the entire document (say it returns just one result), whereas querying without "$and" will return only the resulting document id . – Arthur Zennig May 18 '21 at 11:31