Home > front end >  Using projected field in mongodb condition
Using projected field in mongodb condition

Time:10-02

I am trying to calculate something with mongodb aggregation framework. So I need to use projected item ( which is calculated field in projection stage) in another condition, but I can't get result.

Here is the code what I tried.

"$project": {
    "currency": {"$ifNull": ["$voucher_foreign_amount.symbol", "NOT ENTERED" ]},
    "amount": {"$cond": [{"$not": ["$voucher_foreign_amount"]}, "$voucher_amount", "$voucher_foreign_amount.amount"]},
    "voucher_type": 1,
    "voucher_payment_type": 1,
    "voucher_foreign_amount": 1,
    "station": 1,
    "paid": {"$cond": [{"$eq": ["$voucher_type",  "Paid"]}, "$amount", 1]}
   
}

In this projection, I can't get paid field, in my opinion, it's because last condition, doesn't recognize "$amount".

So, how can I use amount field in another field generation?

CodePudding user response:

A new field that we add either we $project/$set=$addFields, exists only after the stage finishes.

The 2 solutions i suggested was

  1. Add one $set stage
{"$set" : {"amount" : {"$cond": [{"$not": ["$voucher_foreign_amount"]}, "$voucher_amount", "$voucher_foreign_amount.amount"]}}},
{"$project": {
    "currency": {"$ifNull": ["$voucher_foreign_amount.symbol", "NOT ENTERED" ]},
    "amount" : 1,
    "voucher_type": 1,
    "voucher_payment_type": 1,
    "voucher_foreign_amount": 1,
    "station": 1,
    "paid": {"$cond": [{"$eq": ["$voucher_type",  "Paid"]}, "$amount", 1]}
}}
  1. Do the caclulation 2 times
{
"$project": {
    "currency": {"$ifNull": ["$voucher_foreign_amount.symbol", "NOT ENTERED" ]},
    "amount": {"$cond": [{"$not": ["$voucher_foreign_amount"]}, "$voucher_amount", "$voucher_foreign_amount.amount"]},
    "voucher_type": 1,
    "voucher_payment_type": 1,
    "voucher_foreign_amount": 1,
    "station": 1,
    "paid": {"$cond": [{"$eq": ["$voucher_type",  "Paid"]},
                               {"$cond": [{"$not": ["$voucher_foreign_amount"]}, "$voucher_amount", "$voucher_foreign_amount.amount"]},
                               1]}
   }
}

You can do it with 2 projects also as you did, but 1 $set with 1 field only is simpler i think.

About perfomance, i dont know how MongoDB will execute them(i tested in the past and i think it optimized it(i tested multiple $map)), for example it might be lazy, and not calculate the $amount unless its value is needed so those 2 stages will look as 1 internally. (in this case the 1st will be faster)

If its not lazy, the second loooks faster.

  • Related