sql >> Databasteknik >  >> NoSQL >> MongoDB

uppdatera tvålagers kapslade objekt baserat på id

Du kan faktiskt lösa ditt problem med uppdateringen metod, men du måste göra det på ett annat sätt om du använder MongoDB 4.2 eller senare. Den andra parametern kan vara $set operation du vill utföra eller en aggregation rörledning. Om du använder det senare har du större frihet att forma data. Så här kan du lösa ditt problem, jag kommer att dela upp efter:

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

Använd först uppdateringen metod som skickar tre parametrar:

  • Filterfråga
  • Aggregationspipeline
  • Alternativ. Här använde jag precis new: true för att returnera det uppdaterade dokumentet och göra det lättare att testa.

Detta är strukturen:

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

Inuti pipelinen behöver vi bara ett steg, $set för att ersätta egenskapen advanced med en array som vi kommer att skapa.

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

Vi mappar först den advanced array för att kunna mappa den kapslade korten array efter:

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

Vi använder variabeln som vi deklarerade på den första kartan och som innehåller den avancerade arrayen som nuvarande objekt som mappas ( adv ) för att komma åt och mappa den kapslade "kort"-arrayen ( $$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",
          }
        }     
      } 
    }
  }
]
...

Till sist kontrollerar vi om det aktuella kort-id:t är lika med det id som söks $eq: [ "$$advcard.id", "main-2-1" ] och returnera det nya kortet om det matchar eller det aktuella kortet:

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

...

Här är ett fungerande exempel på vad som beskrivs:https://mongoplayground.net/p/xivZGNeD8ng




  1. MongoDB uppdaterar inte data automatiskt?

  2. Visa all data som kommer från mongodb och rendera den i doT.js mallmotor

  3. Konvertera MongoDB-fråga till Java

  4. mongoose _id-fältet kan inte tas bort