Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

$elemMatch query in MongoDB

I have a collection 'name' with 2 documents of the structure :

doc 1:

    {
    a: 1
    b : [{name:"AAA",age:10},
         {name:"BBB",age:12},
         {name:"CCC",age:13}]
    }

doc 2 :

    {
    a: 2
    b : [{name:"DDD",age:14},
         {name:"EEE",age:15},
         {name:"FFF",age:16}]
    }

Since I am new to MongoDB, I am trying to find the difference of using the $elemMatch operator and not using it. Basically I am trying to query and find the first doc ( doc 1) with name AAA and age 10. So using the $elemMatch, my query looks like this :

db.name.find({b: {$elemMatch :{name:"AAA",age:10}}})

This query works perfectly fine, but my question is that what's the need to use this query when I can query like this :

db.name.find({b:{name:"AAA",age:10}})

I am sure there should be some reason for $elemMatch, just trying to find the difference. Thanks in advance for the reply !!!

like image 817
Soham Avatar asked Jan 18 '17 17:01

Soham


2 Answers

The key difference is that the second query (without the $elemMatch) would only match elements in the b array that only contained those two fields, and only in that order.

So the first query would match the following two documents, but the second query wouldn't:

{
a: 1
b: [{name: "AAA", age: 10, city: 'New York'},
    {name: "BBB", age: 12, city: 'Paris'},
    {name: "CCC", age: 13, city: 'London'}]
}

{
a: 1,
b: [{age: 10, name: "AAA"},
    {name: "BBB", age: 12},
    {name: "CCC", age: 13}]
}
like image 84
JohnnyHK Avatar answered Sep 28 '22 02:09

JohnnyHK


Another important difference is that how Mongo uses indexes.

If we have declared a multi-key-compound index:

db.name.createIndex({ "b.name": 1, "b.age": 1 })

And we execute this:

db.name.explain().find({
  b: {
    name: "DDD",
    age: 14
  }
})

we get:

"winningPlan" : {
  "stage" : "COLLSCAN",

If we execute this:

db.name.explain().find({
  b: {
    $elemMatch: {
      name: "DDD",
      age: 14
    }
  }
})

we get:

"winningPlan" : {
  "stage" : "FETCH",
  "inputStage" : {
    "stage" : "IXSCAN",

But if we have a simple multi-key index in the array:

db.name.createIndex({b: 1})

The above index will be used in this query:

db.name.explain().find({
  b: {
    name: "DDD",
    age: 14
  }
})

And under my very un-professional profiling tests looks like this is faster.

like image 34
fguillen Avatar answered Sep 28 '22 03:09

fguillen