MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

atualize o objeto aninhado de duas camadas com base no id


Você pode resolver seu problema com a atualização , mas você precisa fazer isso de uma maneira diferente se estiver usando o MongoDB 4.2 ou posterior. O segundo parâmetro pode ser o $set operação que você deseja executar ou uma aggregation encanamento. Usando o mais tarde você tem mais liberdade para moldar os dados. Esta é a maneira que você pode resolver seu problema, vou detalhar depois:
db.collection.update({
  "cards.advanced.unit": 2
},
[
  {
    $set: {
      "cards.advanced": {
        $map: {
          input: "$cards.advanced",
          as: "adv",
          in: {
            cards: {
              $map: {
                input: "$$adv.cards",
                as: "advcard",
                in: {
                  $cond: [
                    {
                      $eq: [
                        "$$advcard.id",
                        "main-2-1"
                      ]
                    },
                    {
                      title: "this is a NEW updated card",
                      id: "$$advcard.id"
                    },
                    "$$advcard"
                  ]
                }
              }
            },
            unit: "$$adv.unit"
          }
        }
      }
    }
  }
],
{
  new: true,
  
});

Primeiro, use a atualização método passando três parâmetros:
  • Filtrar consulta
  • Funil de agregação
  • Opções. Aqui eu usei new: true para devolver o documento atualizado e facilitar o teste.

Esta é a estrutura:
db.collection.update({
  "cards.advanced.unit": 2
},
[
  // Pipeline
],
{
  new: true,
});

Dentro do pipeline precisamos apenas de um estágio, o $set para substituir a propriedade advanced com um array que vamos criar.
...
[
  {
    $set: {
      "cards.advanced": {
        // Our first map
      } 
    }
  }
]
...

Primeiro mapeamos o advanced array para poder mapear o array de cartões aninhados após:
...
[
  {
    $set: {
      "cards.advanced": {
        $map: {
          input: "$cards.advanced",
          as: "adv",
          in: {
            // Here we will map the nested array
          }
        }     
      } 
    }
  }
]
...

Usamos a variável que declaramos no primeiro mapa e que contém o item atual do array avançado que está sendo mapeado ( adv ) para acessar e mapear a matriz "cards" aninhada ( $$adv.cards ):
...
[
  {
    $set: {
      "cards.advanced": {
        $map: {
          input: "$cards.advanced",
          as: "adv",
          in: {
            cards: {
              $map: {
                input: "$$adv.cards",
                as: "advcard",
                in: {
                // We place our condition to check for the chosen card here
                }
              }
            },
            unit: "$$adv.unit",
          }
        }     
      } 
    }
  }
]
...

Por fim, verificamos se o id do cartão atual é igual ao id que está sendo pesquisado $eq: [ "$$advcard.id", "main-2-1" ] e devolva o novo cartão se corresponder ou o cartão atual:
...
{
  $cond: [
    {
      $eq: [
        "$$advcard.id",
        "main-2-1"
      ]
    },
    {
      title: "this is a NEW updated card",
      id: "$$advcard"
    },
    "$$advcard"
  ]
}

...

Aqui está um exemplo prático do que está descrito:https://mongoplayground.net/p/xivZGNeD8ng