gdollardollar
gdollardollar

Reputation: 545

Dynamic field path for $set in mongo db aggregation

I have documents containing multilingual data. A simplified version looks like:

  {
    languages: [
      "en",
      "fr"
    ],
    title: {
      en: "Potato Gratin",
      fr: "Gratin de pomme de terre"
    },    
  }

Important parts are:

What I would like to do is querying that document for a specific language and either

I-e querying the above document in french should return {"title": "Gratin de pomme de terre"} and if queried in chinese, it should return {"title": "Potato Gratin"}

I have a playground setup: https://mongoplayground.net/p/CP0Z20dTpgy. I have it so that it sets a lang property that the output should be in. I would then like to have a stage that looks like "$set": {"title": "$title.$lang"} but it complains that a field path component should not start with $, which I am guessing means that mongo does not support dynamic field paths ?

Any idea on how to achieve something like that?

Some notes:

Upvotes: 1

Views: 1019

Answers (1)

matthPen
matthPen

Reputation: 4343

You have to transform your object to an array with $objectToArray, filter this array and get element 0 of it. Then you can transform back you value.

db.collection.aggregate([
  {
    "$match": {
      "_id": BinData(0, "3BByrilZQ2GTdlXG0nrGXw=="),
      
    },
  },
  {
    "$set": {
      "lang": {
        "$cond": [
          {
            "$in": [
              "zh",
              "$languages"
            ]
          },
          "zh",
          {
            "$first": "$languages"
          }
        ]
      }
    }
  },
  {
    $addFields: {
      title: {
        "$arrayElemAt": [
          {
            "$filter": {
              "input": {
                "$objectToArray": "$title"
              },
              "as": "title",
              "cond": {
                $eq: [
                  "$$title.k",
                  "$lang"
                ]
              }
            }
          },
          0
        ]
      }
    }
  },
  {
    $addFields: {
      title: "$title.v"
    }
  }
])

Of course, you have to pass your 'zh' as parameter in your code, on both places.

You can test it here

Upvotes: 2

Related Questions