Использование проецируемого поля в состоянии mongodb

#mongodb

Вопрос:

Я пытаюсь что-то рассчитать с помощью платформы агрегации mongodb. Поэтому мне нужно использовать проецируемый элемент ( который является вычисляемым полем на этапе проектирования) в другом состоянии, но я не могу получить результат.

Вот код, который я пробовал.

 "$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]}
   
}
 

В этой проекции я не могу получить поле «оплата», на мой взгляд, это потому, что последнее условие не распознает «сумму в долларах».

Итак, как я могу использовать поле сумма в другом поколении полей?

Комментарии:

1. $amount существует только после завершения проекта, решением может быть добавление $set этапа, просто чтобы установить amount вышеуказанный проект, или сохранить 1 проект и рассчитать сумму в 2 раза(второй выглядит быстрее)

2. @Takis_ спасибо, два проекта решили мою проблему, если вы ответите на нее, я приму.

Ответ №1:

Новое поле, которое мы добавляем либо мы $project / $set = $addFields , существует только после завершения этапа.

2 решения, которые я предложил, были

  1. Добавьте один $set этап
 {"$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. Сделайте каклуляцию 2 раза
 {
"$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]}
   }
}
 

Вы можете сделать это с 2 проектами также, как и вы, но 1 $set с 1 полем, я думаю, проще.

Что касается производительности, я не знаю, как MongoDB будет их выполнять(я тестировал в прошлом и думаю, что он оптимизировал их(я тестировал несколько $map )), например, он может быть ленивым и не вычислять $amount , если его значение не требуется, поэтому эти 2 этапа будут выглядеть как 1 внутренне. (в этом случае 1-й будет быстрее)

Если он не ленивый, второй выглядит быстрее.