Sim*_*iel 5 mongodb mongodb-query
查询运算符的使用有逻辑上的区别吗$and
db.collection.find({$and: [{"array.field1": "someValue"}, {"array.field2": 3}]})
Run Code Online (Sandbox Code Playgroud)
以及投影算子的用法$elemMatch
db.collection.find({array: {$elemMatch: {field1: "someValue", field2: 3}}})
Run Code Online (Sandbox Code Playgroud)
查找包含数组内对象字段的文档?
我将用一个例子来解释这一点。考虑收藏arrays。它有一个名为的字段arr,它是嵌入文档的数组(带有字段a和b)。
集合中的一些文档arrays:
{ "_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" } ] }
Run Code Online (Sandbox Code Playgroud)
我想查找带有数组嵌入文档字段a="a1"AND的所有文档b="b1"。请注意,这必须位于数组的同一元素嵌入文档中。我为此使用$elemMatch并获得所需的结果。
> db.arrays.find( { arr: { $elemMatch: { a: "a1", b: "b1" } } } )
==>
{ "_id" : 1, "arr" : [ { "a" : "a1", "b" : "b1" }, { "a" : "a2", "b" : "b2" } ] }
Run Code Online (Sandbox Code Playgroud)
现在,如果我像下面的查询一样使用$and运算符,结果将不正确。如您所见,选择了一个附加文档。该查询使用数组嵌入文档字段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" } ] }
Run Code Online (Sandbox Code Playgroud)
因此,使用$and运算符并不是用于此目的(即查询子文档数组的多个字段)。
另外,要查询数组嵌入文档字段(只有一个字段),则$elemMatch不需要,例如:
> 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" } ] }
Run Code Online (Sandbox Code Playgroud)
您的第一个查询将找到文档,其中数组至少有一个 field1= somevalue 的元素和至少一个 field2=3 的元素。两个元素可以不同。第二个将检索数组中至少有一个元素同时匹配两个条件的文档。这是一个数据样本来解释:
{
array: [
{
field1: 1,
},
{
field2: 2
},
{
field1: 1,
field2: 3
},
]
},
{
array: [
{
field1: 1,
field2: 2
},
{
field2: 3
}
]
},
{
array: [
{
field1: 1,
field2: "other"
},
{
field2: 2
}
]
}
Run Code Online (Sandbox Code Playgroud)
第一个查询
db.collection.find({"array.field1": 1,"array.field2": 2}) (相当于你的 $and 语法)
将返回三个文件,
db.collection.find({array: {$elemMatch: {field1: 1, field2: 2}}})
将仅返回第二个文档(唯一一个具有匹配两个条件的元素的文档)
编辑:第一个查询的逻辑运算符是 OR,第二个查询的逻辑运算符是 AND,在数组元素级别。