Is there any logical difference between the usage of the query operator $and
db.collection.find({$and: [{\"array.field1\": \"someValue\"}, {\"array.
I will explain this with an example. Consider the collection arrays
. It has a field called arr
which is an array of embedded documents (with fields a
and b
).
Some documents in the arrays
collection:
{ "_id" : 1, "arr" : [ { "a" : "a1", "b" : "b1" }, { "a" : "a2", "b" : "b2" } ] }
{ "_id" : 2, "arr" : [ { "a" : "a1", "b" : "b11" }, { "a" : "a2", "b" : "b22" } ] }
{ "_id" : 3, "arr" : [ { "a" : "a2", "b" : "b1" }, { "a" : "a", "b" : "b1" } ] }
{ "_id" : 4, "arr" : [ { "a" : "a1", "b" : "b91" }, { "a" : "a29", "b" : "b1" } ] }
I want to find all documents with the array embedded-document fields a="a1"
AND b="b1"
. Note this must be within the same element embedded-document of the array. I use $elemMatch for this and get the desired result.
> db.arrays.find( { arr: { $elemMatch: { a: "a1", b: "b1" } } } )
==>
{ "_id" : 1, "arr" : [ { "a" : "a1", "b" : "b1" }, { "a" : "a2", "b" : "b2" } ] }
Now, if I use the $and operator like in the following query, the results are not correct. As you can see an additional document is selected. The query worked with the array embedded-document fields a="a1"
OR b="b1"
.
> db.arrays.find({$and: [ { "arr.a": "a1" }, { "arr.b": "b1" } ] } )
==>
{ "_id" : 1, "arr" : [ { "a" : "a1", "b" : "b1" }, { "a" : "a2", "b" : "b2" } ] }
{ "_id" : 4, "arr" : [ { "a" : "a1", "b" : "b91" }, { "a" : "a29", "b" : "b1" } ] }
So, using the $and
operator is NOT intended for this purpose (i.e., querying on multiple fields of an array of sub-documents).
Also, to query on an array embedded-document field (only one field) the $elemMatch
is not required, for example:
> db.arrays.find( { "arr.a": "a2" } )
==>
{ "_id" : 1, "arr" : [ { "a" : "a1", "b" : "b1" }, { "a" : "a2", "b" : "b2" } ] }
{ "_id" : 2, "arr" : [ { "a" : "a1", "b" : "b11" }, { "a" : "a2", "b" : "b22" } ] }
{ "_id" : 3, "arr" : [ { "a" : "a2", "b" : "b1" }, { "a" : "a", "b" : "b1" } ] }
Your first query will find documents, where array have at least one element with field1= somevalue and at least one element with field2=3. Both elements can be different. The second one will retrieve documents where array have at least one element matching the two conditions simultaneously. Here's a data sample to explain :
{
array: [
{
field1: 1,
},
{
field2: 2
},
{
field1: 1,
field2: 3
},
]
},
{
array: [
{
field1: 1,
field2: 2
},
{
field2: 3
}
]
},
{
array: [
{
field1: 1,
field2: "other"
},
{
field2: 2
}
]
}
The first query
db.collection.find({"array.field1": 1,"array.field2": 2}) (equivalent to your $and syntax)
will returne the three documents,
db.collection.find({array: {$elemMatch: {field1: 1, field2: 2}}})
will return only the second document (the only one having an element matching both criterias)
EDIT : The logical operator of the first query is OR, for the second one it's AND, at level of array element.