Home > database >  Filter only needed object from nested array of object mongodb aggregation
Filter only needed object from nested array of object mongodb aggregation

Time:11-10

I am trying to filter nested array of object and i need only matching property object. Facing issue getting expected output of my aggregation. In sample data, There are more fields at top level, but those fields are not required for this aggregation output.

Sample data. From above below data, Need to filter only subscribed milestone status and return that. milestone object's last index always has updated property which we need to check and filter based on.

{

    active: 'true',
    time:'',
    unified_invitees: [
        {
            _id: 1,
            milestone_status: [
                {
                    milestone:"draft"
                },
                {
                    milestone:"deleted"
                },
            ]
        },
        {
            _id: 2,
            milestone_status: [
                {
                    milestone:"draft"
                },
                {
                    milestone:"deleted"
                },
            ]
        },
        {
            _id: 3,
            milestone_status: [
                {
                    milestone:"draft"
                },
                {
                    milestone:"subscribed"
                },
            ]
        },
    ]
}

I have tried following solutions but doesn't seem to work as expected.

addFields

{
    "invitee":{
          $filter: { input: "$unified_invitees.milestone_status", cond: { $eq: [ "$$this.milestone", "subscribed" ] } }
        }
}
{
  "unified_invitees": {
      "$arrayElemAt": [
          {
              "$filter": {
                  "input": "$unified_invitees",
                  "as": "comp",
                  "cond": {
                      "$ne": [ "$$comp.milestone_status.milestone", "deleted" ]
                  }
              }
          }, 0
      ]
  }
}

filter map

{
    "documents": {
      $map: {
        "input": "$unified_invitees",
        "as": "d",
        "in": {
          "milestone_status": {
            $filter: {
              "input": "$$d.milestone_status",
              "as": "s",
              "cond": {
                $eq: [
                  "$$s.milestone",
                  "subscribed"
                ],
              }
            }
          }
        }
      }
    }
  }

CodePudding user response:

You can use the $anyElementTrue operator along with $map to filter the inner array:

db.collection.aggregate([
    {
        $addFields: {
            unified_invitees: {
                $filter: {
                    input: "$unified_invitees",
                    as: "un",
                    cond: {
                        $anyElementTrue: {
                            $map: {
                                input: "$$un.milestone_status",
                                as: "ms",
                                in: { $eq: [ "$$ms.milestone", "subscribed" ] }
                            }
                        }
                    }
                }
            }
        }
    }
])

The role of $map operator here is to return an array of boolean values representing whether each milestone_status is set to subscribed.

MongoDB Playground

  • Related