MongoDB:$elemMatch和$and在数组内查找对象有什么区别?

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)

查找包含数组内对象字段的文档?

pra*_*ad_ 9

我将用一个例子来解释这一点。考虑收藏arrays。它有一个名为的字段arr,它是嵌入文档的数组(带有字段ab)。

集合中的一些文档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)


mat*_*Pen 4

您的第一个查询将找到文档,其中数组至少有一个 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,在数组元素级别。