MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

aggiorna l'oggetto nidificato a due livelli in base all'id

Puoi effettivamente risolvere il tuo problema con l'aggiornamento metodo, ma devi farlo in un modo diverso se stai usando MongoDB 4.2 o successivo. Il secondo parametro può essere $set operazione che si desidera eseguire o una aggregation tubatura. Usando il successivo hai più libertà nel modellare i dati. Questo è il modo in cui puoi risolvere il tuo problema, analizzerò dopo:

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

Innanzitutto usa l'aggiornamento metodo che passa tre parametri:

  • Richiesta filtro
  • Condotto di aggregazione
  • Opzioni. Qui ho appena usato new: true per restituire il documento aggiornato e facilitarne il test.

Questa è la struttura:

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

All'interno della pipeline abbiamo solo bisogno di uno stadio, il $set per sostituire la proprietà advanced con un array creeremo.

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

Per prima cosa mappiamo l'advanced array per poter mappare l'array di carte nidificate dopo:

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

Usiamo la variabile che abbiamo dichiarato sulla prima mappa e che contiene l'elemento corrente dell'array avanzato che viene mappato ( adv ) per accedere e mappare l'array "cards" annidato ( $$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",
          }
        }     
      } 
    }
  }
]
...

Infine controlliamo se l'ID della carta corrente è uguale all'id cercato $eq: [ "$$advcard.id", "main-2-1" ] e restituire la nuova carta se corrisponde o la carta corrente:

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

...

Ecco un esempio funzionante di quanto descritto:https://mongoplayground.net/p/xivZGNeD8ng