How to have temp variables in $reduce stage?

"$project": {
  match: {
    "$reduce": {
      "input": "$matches",
        "in": {
          x: {"$cond": {
            "if": { "$gt": [ "$$this.score",  "$$value.score"] },
            "then": "$$this.x",
            "else": "$$value.x"
          } },
          y: {"$cond": {
            "if": { "$gt": [ "$$this.score",  "$$value.score"] },
            "then": "$$this.y",
            "else": "$$value.y"
          } },
          z: {"$cond": {
            "if": { "$gt": [ "$$this.score",  "$$value.score"] },
            "then": "$$this.z",
            "else": "$$value.z"
          } },
          ...
}},

In a single aggregation pipeline, I want to update many fields base on the same condition, is it possible to let me only write one $cond expression so that this condition test will only run once?
All I want to get is a boolean value (True or False) which will be returned by the condition, getting this value will require both $$this and $$value, and we can’t modify them within $reduce, if there is any way to create a temp variable here, this problem will be solved, $let expression can’t work with $reduce expression here now.

I am pretty sure you simply have to factor your $cond out of each field expression. I think the following should work.

"in": {
    "$cond": {
         "if": { "$gt": [ "$$this.score",  "$$value.score"] },
          "then": {
              x: "$$this.x",
              y: "$$this.y",
              z: "$$this.z"
          } ,
          "else": {
              x: "$$value.x",
              y: "$$value.y",
              z: "$$value.z"
          }
    }
}

Rather than using three little dots to tell us that there is more stuff, please use a valid JS comment such as

/* more stuff unrelated to this use-case */

This way we do not have to edit out the three little dots when we cut-n-paste what you have published.

1 Like