Home > Blockchain >  Querying Subdocuments in MongoDb Documents and Only Return Matching Subdocuments
Querying Subdocuments in MongoDb Documents and Only Return Matching Subdocuments

Time:06-27

Ive looked here: https://codelikethis.com/lessons/db/mongodb-array-queries and here: https://www.mongodb.com/community/forums/t/what-is-the-best-way-to-query-an-array-of-sub-documents-in-mongodb/115315 to try and figure out how to query only matching subdocuments from a parent document.

Here is an example of the data:

{'testname':'process',
'jobId':"job1",
"vt_cond":"cond1",
"testData":[{
'chip':'c1',
'name':'block1'},
{
'chip':'c1',
'name':'block1'},
{
'chip':'c1',
'name':'block2'},
{
'chip':'c1',
'name':'block3'}]}

It contains subdocuments within the "testData" field. What I want to do is something like the following:

db.collection.find({'jobId':'job1', 'testData.name':'block3'})

and have it return the following:

{'testname':'process',
'jobId':"job1",
"vt_cond":"cond1",
"testData":[{'chip':'c1',
'name':'block3'}]}

I understand that the mongodb documentation states it will query and return a document which matches the conditions in the subdocument query conditions. It does. I get the entire example document as above. Is there anyway where I can make a similar query with similar conditions as above, and only return the parent node with the desired subdocument, instead of ALL the subdocuments?

CodePudding user response:

Option 1: You can use $elemMatch in the project part as follow:

db.collection.find({
  "jobId": "job1",
  "testData.name": "block3"
},
{
 "testData": {
   "$elemMatch": {
      name: "block3"
  }
}
})

Explained:

Find the object and project only the array sub-object that match the criteria

Attention: This is only working if you need only 1x matching element from array , if there is more then one element in the array matching the criteria better use Option 2.

Playground

Option 2: aggregate/$filter ( cover the case when you have more then one objects in the array matching by the filter )

  db.collection.aggregate([
 {
  $match: {
  "jobId": "job1",
  "testData.name": "block3"
  }
 },
 {
  "$addFields": {
   "testData": {
    "$filter": {
      "input": "$testData",
      "as": "t",
      "cond": {
        $eq: [
          "$$t.name",
          "block3"
          ]
        }
      }
    }
   }
 }
])

Explained:

  1. Match the document
  2. Filter only the matching objects inside the array of objects

Playground 2

  • Related