Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

211
Visualizações
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 Respostas
Responde à pergunta

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda