I have some documents listed in a stage of aggregation pipeline like this:
[{
obj1:{code:"123"},
obj2:{code:"654"},
obj3:{code:"abc"},
obj4:{code:"xyz"},
type:"obj1",
},{
obj1:{code:"123"},
obj2:{code:"654"},
obj3:{code:"abc"},
obj4:{code:"xyz"},
type:"obj2",
},{
obj1:{code:"123"},
obj2:{code:"654"},
obj3:{code:"abc"},
obj4:{code:"xyz"},
type:"obj4",
}]
In the same aggregation pipeline, Without using $switch cases, is it possible that in each objects we project the code field for it's respective type value in $project stage?
Result should be:
[{
obj1:{code:"123"},
obj2:{code:"654"},
obj3:{code:"abc"},
obj4:{code:"xyz"},
type:"obj1",
code:$type.code // should return "123"
},{
obj1:{code:"123"},
obj2:{code:"654"},
obj3:{code:"abc"},
obj4:{code:"xyz"},
type:"obj2",
code:$type.code // should return "654"
},{
obj1:{code:"123"},
obj2:{code:"654"},
obj3:{code:"abc"},
obj4:{code:"xyz"},
type:"obj4",
code:$type.code // should return "xyz"
}]
Thank you in Advance.
CodePudding user response:
You can use $objectToArray first to be able to filter by your $$ROOT
keys and then use $filter to match against type
field. The $let operator allows you to have it as one-stage pipeline:
db.collection.aggregate({
$addFields: {
code: {
$let: {
vars: {
match: {
$first: {
$filter: {
input: { $objectToArray: "$$ROOT" },
cond: { $eq: [ "$type", "$$this.k" ] }
}
}
}
},
in: "$$match.v.code"
}
}
}
})