mongodb

find() command filtering and retrieving a list of elements from a document?


I have the following document:

{
  _id: '99999999-2795704-R11-IV1_17486713998556251',
  forms: [
    {
      parentId: 'PID_174867139985677038128',
      formName: 'Hello World 001',
      version: [
        {
          formId: '174867139985677038128',
          refLineId: 'e3d93310d3044cc38a3a3156670e9225-cc2bf35662df4ceca38d43f583039611-20',
          version: '1',
          startDate: '2025-05-08',
          status: 'Active'
        }
      ]
    },
    {
      parentId: 'PID_174867139985677038129',
      formName: 'Hello World 002',
      version: [
        {
          formId: '174867139985677038129',
          refLineId: 'e3d93310d3044cc38a3a3156670e9225-cc2bf35662df4ceca38d43f583039611-21',
          version: '1',
          startDate: '2025-05-09',
          status: 'Active'
        }
      ]
    }
  ]
}

I want to run a find() command, but I want it to retrieve only one of the Forms (by name) & I want also to return only a specified set of fields.

db["flows"].find({"_id":{"$regex":"22316281-2795704-R11-IV1"}}, {"forms": {"$elemMatch": {"formName": "Hello World 001"}}})

db["flows"].find({"_id":{"$regex":"22316281-2795704-R11-IV1"}}, {"forms,version.status": true, "forms.version.formId": true})

However, I have been unable to mix the two in a single query. The following query returns «Parth collision at forms.version.status remaining portion version.status».

db["flows"].find({"_id":{"$regex":"22316281-2795704-R11-IV1"}}, {"forms": {"$elemMatch": {"formName": "Hello World 001"}}, "forms.version.status": true})

How can I achieve that?

{
   _id: '99999999-2795704-R11-IV1_17486713998556251',
   forms: [
     {
       formName: 'Hello World 001',
       version: [
         {
           formId: '174867139985677038128',
           version: '1',
           status: 'Active'
         }
       ]
     }
   ]
}

Solution

  • Use aggregation:

    db.flows.aggregate([
      { $match: { _id: { $regex: "22316281-2795704-R11-IV1" } } },
      { $unwind: "$forms" },
      { $match: { "forms.formName": "Hello World 001" } },
      {
        $project: {
          "forms.formName": true,
          "forms.version.formId": true,
          "forms.version.status": true
        }
      }
    ])
    

    Or use $elemMatch and ignore deep projection:

    db.flows.find(
      { _id: { $regex: "22316281-2795704-R11-IV1" } },
      { "forms": { "$elemMatch": { "formName": "Hello World 001" } } }
    )