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
.