Dynamic new field value based on multiple condition of other field value in Mongodb Aggregation

Viewed 31

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.

1 Answers

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"
            }
        }
    }
})

Mongo Playground

Related