Search code examples
mongodbmongodb-queryaggregation-framework

Filter Out records inside Nested array Mongo DB Aggregation


I am Trying to filter our records from an Inner Array in the Mongo Collection . Example is given below :

{
 "cId":23456,
 "description":"car",
  "brand": [{
    "bId":23,
    "bName":"toyota",
     "model":[{
      "mName":"camry",
      "vId":"12"
      },
      {
      "mName":"corolla",
      "vId":"13"
      }]
   },{
    "bId":24,
    "bName":"honda",
     "model":[{
      "mName":"accord",
      "vId":"14"
      },
      {
      "mName":"civic",
      "vId":"15"
      }]
   }]
  }

I want to filter out records from the inner model array, like if the input "civic" , My output should be as below :

{
 "cId":23456,
 "description":"car",
  "brand": [{
    "bId":24,
    "bName":"honda",
     "model":[
      {
      "mName":"civic",
      "vId":"15"
      }]
   }]
  }

I tried multiple unwind to unwind the inner array, but not able to group back to required format as its inner array.


Solution

  • Perhaps something like this:

    db.collection.aggregate([
    {
     $match: {
       "brand.model.mName": "civic"
     }
    },
    {
    "$addFields": {
      "brand": {
        "$filter": {
          "input": {
            "$map": {
              "input": "$brand",
              "as": "b",
              "in": {
                "$mergeObjects": [
                  "$$b",
                  {
                    "model": {
                      "$filter": {
                        "input": "$$b.model",
                        "as": "m",
                        "cond": {
                          "$eq": [
                            "$$m.mName",
                            "civic"
                          ]
                        }
                      }
                    }
                  }
                ]
              }
            }
          },
          "as": "fb",
          "cond": {
            "$ne": [
              "$$fb.model",
              []
              ]
            }
           }
         }
        }
       }
    ])
    

    Explained:

    1. Match only documents having brand.model.mName: civic
    2. filter model.mName: civic walking over all brand array removing the filtered empty models:[].

    Playground