MongoDB: what is the difference between $elemMatch and $and to find objects inside array?

佐手、 提交于 2019-12-11 15:41:17

问题


Is there any logical difference between the usage of the query operator $and

db.collection.find({$and: [{"array.field1": "someValue"}, {"array.field2": 3}]})

and the usage of the projection operator $elemMatch

db.collection.find({array: {$elemMatch: {field1: "someValue", field2: 3}}})

to find documents which contain the object fields inside an array?


回答1:


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.




回答2:


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" } ] }


来源:https://stackoverflow.com/questions/58384199/mongodb-what-is-the-difference-between-elemmatch-and-and-to-find-objects-insi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!