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

前端 未结 2 670
不思量自难忘°
不思量自难忘° 2021-01-24 01:15

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

db.collection.find({$and: [{\"array.field1\": \"someValue\"}, {\"array.         


        
相关标签:
2条回答
  • 2021-01-24 02:00

    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" } ] }
    
    0 讨论(0)
  • 2021-01-24 02:12

    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.

    0 讨论(0)
提交回复
热议问题