sql >> Base de Datos >  >> NoSQL >> MongoDB

actualice el objeto anidado de dos capas en función de la identificación

De hecho, puede resolver su problema con la actualización método, pero debe hacerlo de una manera diferente si está utilizando MongoDB 4.2 o posterior. El segundo parámetro puede ser el $set operación que desea realizar o una aggregation tubería. Usando el último, tiene más libertad para dar forma a los datos. Esta es la forma en que puede resolver su problema, lo desglosaré después:

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,
  
});

Primero con el uso de la actualización método que pasa tres parámetros:

  • Consulta de filtro
  • Canalización de agregación
  • Opciones. Aquí solo usé new: true para devolver el documento actualizado y facilitar la prueba.

Esta es la estructura:

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

Dentro de la canalización solo necesitamos una etapa, el $set para reemplazar la propiedad advanced con una matriz que crearemos.

...
[
  {
    $set: {
      "cards.advanced": {
        // Our first map
      } 
    }
  }
]
...

Primero mapeamos el advanced matriz para poder mapear la matriz de tarjetas anidadas después de:

...
[
  {
    $set: {
      "cards.advanced": {
        $map: {
          input: "$cards.advanced",
          as: "adv",
          in: {
            // Here we will map the nested array
          }
        }     
      } 
    }
  }
]
...

Usamos la variable que declaramos en el primer mapa y que contiene el elemento actual de la matriz avanzada que se está mapeando ( adv ) para acceder y mapear la matriz de "tarjetas" anidadas ( $$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 último, verificamos si la identificación de la tarjeta actual es igual a la identificación que se busca $eq: [ "$$advcard.id", "main-2-1" ] y devolver la nueva tarjeta si coincide o la tarjeta actual:

...
{
  $cond: [
    {
      $eq: [
        "$$advcard.id",
        "main-2-1"
      ]
    },
    {
      title: "this is a NEW updated card",
      id: "$$advcard"
    },
    "$$advcard"
  ]
}

...

Aquí hay un ejemplo práctico de lo que se describe:https://mongoplayground.net/p/xivZGNeD8ng