How to group data and return the rest fields?

I want to filter the report field, where m_name = "ABC", and group it back.
Here’s my sample data:

{
    "_id" : ObjectId("63f82b8619e8f81b7009d2c3"),
    "type" : "test"
    "created_at" : date
    "created_by" : "admin",
    "report" : [
        {
            "name" : "Day 3",
            "date" : date
            "m_name" : "ABC",
            "created_by" : "admin",
            "created_at" :date
        },
        {
            "name" : "Day 2",
            "date" :date,
            "created_by" : "admin",
            "m_name" : "ABC",
            "created_at" : date
        },
        {
            "name" : "test",
            "date" : date
            "m_name": "123"
            "created_by" : "admin",
            "created_at" : date,
        },
    ],
   ... 20 fields

}

Here’s my pipeline:

      .aggregate([ 
       {
          $unwind: "report",
        },
        {
          $match: {
            "report.m_name": "ABC",
          },
        },
        {
          $group: {
            _id: "$_id",
            report: {
              $push: "$report",
            },
            
          },
        },
       ])

If do like this, output only have _id and report, how to return all the rest fields?
I’ve tried the $$ROOT, but it embedded in a object, I want the output like this:

{
    "_id" : ObjectId("63f82b8619e8f81b7009d2c3"),
    "type" : "test"
    "created_at" : date
    "created_by" : "admin",
    "report" : [
        {
            "name" : "Day 3",
            "date" : date
            "m_name" : "ABC",
            "created_by" : "admin",
            "created_at" :date
        },
        {
            "name" : "Day 2",
            "date" :date,
            "created_by" : "admin",
            "m_name" : "ABC",
            "created_at" : date
        },
    ],
   ... 20 fields

}

I know project (type: {$first: “$type”},) will do, but there are 20 fields, any other simpler way to do this?

Hello @elss,

Why need to unconstruct an array while there is a $filter operator, you can filter the array by specifying the condition,

Would be something like this,

 .aggregate([
  {
    $addFields: {
      report: {
        $filter: {
          input: "$report",
          cond: { $eq: ["$$this.m_name", "ABC"] }
        }
      }
    }
  }
])
2 Likes

I think you still need to

but as the first stage of the pipeline.

Without the $match the $addFields/$filter will produce all documents, even the one that do not have report.m_name:ABC. The report array will be empty but all documents from the collection will be output which was not the case with $unwind/$match.

The pipeline would then look like:

[
    {  "$match" : { /* from the original pipeline */
            "report.m_name": "ABC",
    }  } ,
    { "$addFields" : { /* from turivishal's pipeline */
        "report" : { "$filter" : {
            "input" : "$report",
            "cond" : { "$eq" : [ "$$this.m_name" , "ABC" ] }
        } }
    } }
]
2 Likes

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.