sql >> Databáze >  >> NoSQL >> MongoDB

aktualizovat dvouvrstvý vnořený objekt na základě id

Ve skutečnosti můžete svůj problém vyřešit pomocí aktualizace metodu, ale musíte to udělat jiným způsobem, pokud používáte MongoDB 4.2 nebo novější. Druhým parametrem může být $set operace, kterou chcete provést, nebo aggregation potrubí. Při použití pozdějšího máte větší svobodu při tvarování dat. Toto je způsob, jak můžete vyřešit svůj problém, rozepíšu se po:

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

Nejprve pomocí aktualizace metoda předávání tří parametrů:

  • Filtrovat dotaz
  • Agregační kanál
  • Možnosti. Zde jsem právě použil new: true vrátit aktualizovaný dokument a usnadnit testování.

Toto je struktura:

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

Uvnitř potrubí potřebujeme pouze jeden stupeň, $set nahradit vlastnost advanced s polem, které vytvoříme.

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

Nejprve namapujeme advanced pole, aby bylo možné mapovat pole vnořených karet po:

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

Používáme proměnnou, kterou jsme deklarovali na první mapě a která obsahuje aktuální mapovanou položku pokročilého pole ( adv ) pro přístup a mapování vnořeného pole „cards“ ( $$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",
          }
        }     
      } 
    }
  }
]
...

Nakonec zkontrolujeme, zda se aktuální ID karty shoduje s hledaným ID $eq: [ "$$advcard.id", "main-2-1" ] a vraťte novou kartu, pokud se shoduje, nebo aktuální kartu:

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

...

Zde je funkční příklad toho, co je popsáno:https://mongoplayground.net/p/xivZGNeD8ng




  1. return database_name ==':memory:' nebo 'mode=memory' v database_name TypeError:argument typu 'WindowsPath' nelze iterovat

  2. MongoDB:pokus o čtení Long z JSON způsobí, že java.lang.Integer nelze přetypovat na java.lang.Long

  3. Golang / MGO -- panika:žádné dostupné servery

  4. Souběžnost v gopkg.in/mgo.v2 (Mongo, Go)