On the surface, it seems like the $and operator is useless because it is implicitly applied when MongoDB processes each expression in the query.
For instance the following query searches for all products where category=”vehicle” AND brand=”toyota”:
db.products.find({ "category":"vehicle", "brand":"toyota" })
However, consider this:
db.products.find({ "category":"fruit", "category":"vehicle", "brand":"toyota" })
It is very logical to think that the above query would not return anything because you are querying for documents where category=”fruit” AND category=”vehicle” AND brand=”toyota”. It turns out that the query will return the same results as the first query, the one where category=”vehicle” AND brand=”toyota”.
What is happening is that when MongoDB is processing expressions in a query it will overwrite expressions that have the same field or operator. In this case, the first expression is “category”:”fruit”. Then the second expression is “category”:”vehicle” and has the same field (“category”) as the first expression, so it will be used instead. The first expression will be completely ignored – overwritten by the second expression.
The same happens for expressions that start with an operator, for instance:
db.products.find({ "$or":[{...}, {...}], "$or":[{...}, {...}] })
The second “$or” expression will overwrite the first one and so the first $or expression will be completely ignored.
In order to avoid this implicit $and operation behaviour, you will have to use the explicit operator:
db.products.find({ "$and":[ {"$or":[{...}, {...}]}, {"$or":[{...}, {...}]} ] })