huwng
huwng

Reputation: 61

MongoDB - how to use $project with $cond in aggregate pipeline

my collection has structure like this:

"listQuestion": [
        {
            "answer_type": 0,
            "listShortAnswer": [],
            "listQuestionChildren": [],
            "quiz_type": 1,
            "listPairing": [],
            "listAnswer": [
                {
                    "is_true": false,
                    "answer_content": " \\[x=-2\\] ",
                    "answer_url_image": "",
                    "answer_url_mp3": "",
                    "answer_id": 136948
                },
                {
                    "is_true": true,
                    "answer_content": " \\[x=-1\\] ",
                    "answer_url_image": "",
                    "answer_url_mp3": "",
                    "answer_id": 136950
                },

I have an aggregation variable called $$isShowAnswer, if it is true, the is_true will be show, or else it won't

here is my projection with $cond

$project: {
    'listAnswer.is_true': {
        $cond: { if: { $eq: ["$$isShowAnswer", false] }, then: "$$REMOVE", else: 1}
    },
},

but the result is like below

                {
                    "answer_content": " \\[x=-2\\] ",
                    "answer_url_image": "",
                    "answer_url_mp3": "",
                    "answer_id": 136948,
                    "is_true": 1
                },
                {
                    "answer_content": " \\[x=-1\\] ",
                    "answer_url_image": "",
                    "answer_url_mp3": "",
                    "answer_id": 136950,
                    "is_true": 1
                },

how can I remove "is_true" field if the condition is correct and do nothing if it's wrong?

Upvotes: 1

Views: 1156

Answers (1)

Wernfried Domscheit
Wernfried Domscheit

Reputation: 59456

In order to update an array you need to use $map. Removing a key by condition is not simple, you can use workaround with $objectToArray and then revert again with $arrayToObject

db.getCollection("collection").aggregate([
   {
      $project: {
         listAnswer: {
            $map: {
               input: "$listAnswer",
               as: 'answer',
               in: {
                  $cond: {
                     if: { $eq: ["$$isShowAnswer", false] },
                     then: { $mergeObjects: ["$$answer", { is_true: 1 }] },
                     else: {
                        $arrayToObject: {
                           $filter: {
                              input: { $objectToArray: "$$answer" },
                              as: 'item',
                              cond: { $ne: ["$$item.k", 'is_true'] }
                           }
                        }
                     }
                  }
               }
            }
         }
      }
   }
])

Another solution would be

  1. {$unwind: "$listAnswer"}
  2. then your { $cond: { if: { $eq: ["$$isShowAnswer", false] }, then: "$$REMOVE", else: 1} }
  3. revert with $group

Upvotes: 2

Related Questions