Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

210
Views
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:

  • title contains translations in the shape <lang> : <text>
  • languages contains the list of supported languages, the fist one being the default language.
  • not all documents support the same languages

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

  • replace the title object by the correct translation if the language is supported
  • replace the title object by the default translation if the language is not

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:

  • In the actual documents I have a lot of these fields so a solution with "$unwind" would be costly.
  • the reason it is structured with languages as keys is that it helps with indexing with Mongo Atlas. Changing the structure to have an array of translations would hurt other parts of the app.
over 4 years ago · Santiago Trujillo
1 answers
Answer question

0

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

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!