Mongodb querying documents

I recently started working on mongodb which is very new for me, Currently I have a confusion on the document querying command “$elemMatch”. I used this tag for selecting documents greater than 10 and less than or equal to 20, and the result it gives, but if I didn’t specify the $elemMatch tag then the output is displayed but the document which didn’t satisfy the condition are also displayed. So can anyone help me in understanding what $elemMatch exactly does ?

@Wwe_Star

This seems weird!!

I tested this and works fine in my environment.

Let me show you the result.

replset:PRIMARY> db.inventory.find()
{ "_id" : ObjectId("66124b3e7d01624ec29e6444"), "instock" : [ { "qty" : 10 } ] }
{ "_id" : ObjectId("66124b507d01624ec29e6445"), "instock" : [ { "qty" : 120 } ] }
{ "_id" : ObjectId("66124b567d01624ec29e6446"), "instock" : [ { "qty" : 500 } ] }
{ "_id" : ObjectId("66124bcc7d01624ec29e6447"), "instock" : [ { "qty" : 5 } ] }

replset:PRIMARY> db.inventory.find({"instock.qty":{$gt:10, $lte:120}});

Output:
{ "_id" : ObjectId("66124b507d01624ec29e6445"), "instock" : [ { "qty" : 120 } ] }

replset:PRIMARY> db.inventory.find({ instock: { $elemMatch: { qty: { $gt: 10, $lte: 500 } } } })

Output:

{ "_id" : ObjectId("66124b507d01624ec29e6445"), "instock" : [ { "qty" : 120 } ] }

{ "_id" : ObjectId("66124b567d01624ec29e6446"), "instock" : [ { "qty" : 500 } ] }

The $elemMatch operator matches documents that contain an array field with at least one element that matches all the specified query criteria.

Exactly, what MongoDB version you are using ?

I’m currently using MongoDB v4.4.29

@Wwe_Star

I again test it with some similar data and with multiple MongoDB version. It appears to be a behaviour rather than a issue.

Let me share the details.

> db.inventory.find()
{ "_id" : ObjectId("6629dc066f6505a637cb585b"), "item" : "journal", "instock" : [ { "warehouse" : "A", "qty" : 5 }, { "warehouse" : "C", "qty" : 15 } ] }
{ "_id" : ObjectId("6629dc066f6505a637cb585c"), "item" : "paper", "instock" : [ { "warehouse" : "A", "qty" : 60 }, { "warehouse" : "C", "qty" : 15 } ] }
{ "_id" : ObjectId("6629dc066f6505a637cb585d"), "item" : "postcard", "instock" : [ { "warehouse" : "B", "qty" : 15 }, { "warehouse" : "C", "qty" : 35 } ] }
{ "_id" : ObjectId("6629dc066f6505a637cb585e"), "item" : "pancard", "instock" : [ { "warehouse" : "A", "qty" : 32 }, { "warehouse" : "C", "qty" : 20 } ] }
{ "_id" : ObjectId("6629e1246f6505a637cb585f"), "item" : "journal", "instock" : [ { "warehouse" : "A", "qty" : 40 }, { "warehouse" : "C", "qty" : 5 } ] }

MongoDB server version: 4.4.29

> db.inventory.find({"instock.qty":{$gt:10, $lte:20}});
{ "_id" : ObjectId("6629dc066f6505a637cb585b"), "item" : "journal", "instock" : [ { "warehouse" : "A", "qty" : 5 }, { "warehouse" : "C", "qty" : 15 } ] }
{ "_id" : ObjectId("6629dc066f6505a637cb585c"), "item" : "paper", "instock" : [ { "warehouse" : "A", "qty" : 60 }, { "warehouse" : "C", "qty" : 15 } ] }
{ "_id" : ObjectId("6629dc066f6505a637cb585d"), "item" : "postcard", "instock" : [ { "warehouse" : "B", "qty" : 15 }, { "warehouse" : "C", "qty" : 35 } ] }
{ "_id" : ObjectId("6629dc066f6505a637cb585e"), "item" : "pancard", "instock" : [ { "warehouse" : "A", "qty" : 32 }, { "warehouse" : "C", "qty" : 20 } ] }
{ "_id" : ObjectId("6629e1246f6505a637cb585f"), "item" : "journal", "instock" : [ { "warehouse" : "A", "qty" : 40 }, { "warehouse" : "C", "qty" : 5 } ] }

> db.inventory.find({ instock: { $elemMatch: { qty: { $gt: 10, $lte: 20 } } } })
{ "_id" : ObjectId("6629dc066f6505a637cb585b"), "item" : "journal", "instock" : [ { "warehouse" : "A", "qty" : 5 }, { "warehouse" : "C", "qty" : 15 } ] }
{ "_id" : ObjectId("6629dc066f6505a637cb585c"), "item" : "paper", "instock" : [ { "warehouse" : "A", "qty" : 60 }, { "warehouse" : "C", "qty" : 15 } ] }
{ "_id" : ObjectId("6629dc066f6505a637cb585d"), "item" : "postcard", "instock" : [ { "warehouse" : "B", "qty" : 15 }, { "warehouse" : "C", "qty" : 35 } ] }
{ "_id" : ObjectId("6629dc066f6505a637cb585e"), "item" : "pancard", "instock" : [ { "warehouse" : "A", "qty" : 32 }, { "warehouse" : "C", "qty" : 20 } ] }

MongoDB server version: 7.0.5

rs0 [direct: primary] test> db.inventory.find({"instock.qty":{$gt:10, $lte:20}});
[
  {
    _id: ObjectId('6629e2b5025cfde7c7b04a4c'),
    item: 'journal',
    instock: [ { warehouse: 'A', qty: 5 }, { warehouse: 'C', qty: 15 } ]
  },
  {
    _id: ObjectId('6629e2b5025cfde7c7b04a4d'),
    item: 'paper',
    instock: [ { warehouse: 'A', qty: 60 }, { warehouse: 'C', qty: 15 } ]
  },
  {
    _id: ObjectId('6629e2b5025cfde7c7b04a4e'),
    item: 'postcard',
    instock: [ { warehouse: 'B', qty: 15 }, { warehouse: 'C', qty: 35 } ]
  },
  {
    _id: ObjectId('6629e2b5025cfde7c7b04a4f'),
    item: 'pancard',
    instock: [ { warehouse: 'A', qty: 32 }, { warehouse: 'C', qty: 20 } ]
  },
  {
    _id: ObjectId('6629e2ba025cfde7c7b04a50'),
    item: 'journal',
    instock: [ { warehouse: 'A', qty: 40 }, { warehouse: 'C', qty: 5 } ]
  }
]
db.inventory.find({ instock: { $elemMatch: { qty: { $gt: 10, $lte: 20 } } } })
[
  {
    _id: ObjectId('6629e2b5025cfde7c7b04a4c'),
    item: 'journal',
    instock: [ { warehouse: 'A', qty: 5 }, { warehouse: 'C', qty: 15 } ]
  },
  {
    _id: ObjectId('6629e2b5025cfde7c7b04a4d'),
    item: 'paper',
    instock: [ { warehouse: 'A', qty: 60 }, { warehouse: 'C', qty: 15 } ]
  },
  {
    _id: ObjectId('6629e2b5025cfde7c7b04a4e'),
    item: 'postcard',
    instock: [ { warehouse: 'B', qty: 15 }, { warehouse: 'C', qty: 35 } ]
  },
  {
    _id: ObjectId('6629e2b5025cfde7c7b04a4f'),
    item: 'pancard',
    instock: [ { warehouse: 'A', qty: 32 }, { warehouse: 'C', qty: 20 } ]
  }
]

So for both the versions we observed similar output. Under find() conditions if any one conditions meets it prints the result although $elemMatch ensures all conditions meets in the same array element otherwise the result is discarded.

I hope this make clear about the differences!

Yeah,

So if we simply give the condition in find() method then it will display the results which match any one of the condition
And, If we use ‘$elemMatch’ then it shows the result which matches all conditions in the find() method
isn’t it ?

@Wwe_Star

Yes, you are correct!!

You will observe the similar behaviour in other collections and data as well. Let us know if see any different behaviour or result set.