Zde se pokoušíte přidat novou položku do pole pouze tam, kde položka neexistuje, a také vytvořit nový dokument, kde neexistuje. Vyberete $addToSet
protože chcete, aby byly položky jedinečné, ale ve skutečnosti je skutečně chcete, aby byly jedinečné pouze pomocí „a“.
Takže $addToset
to neudělá a spíše je třeba "otestovat" přítomný prvek. Ale skutečný problém je v tom, že není možné dělat to a zároveň "upsovat". Logika nemůže fungovat, protože nový dokument bude vytvořen vždy, když nebude prvek pole nalezen, místo aby se k prvku pole přidal, jak chcete.
Chyby aktuální operace jsou záměrně $addToSet
nelze použít k "vytvoření" pole, ale pouze k "přidání" členů do existujícího pole. Ale jak již bylo řečeno, máte jiné problémy s dosažením logiky.
Zde potřebujete sekvenci aktualizačních operací, z nichž se každá „pokusí“ provést svou očekávanou akci. To lze provést pouze pomocí více příkazů:
// attempt "upsert" where document does not exist
// do not alter the document if this is an update
db.test.update(
{ "name": "abc" },
{ "$setOnInsert": { "config": [{ "a": 1, "b": 2 }] }},
{ "upsert": true }
)
// $push the element where "a": 1 does not exist
db.test.update(
{ "name": "abc", "config.a": { "$ne": 1 } },
{ "$push": { "config": { "a": 1, "b": 2 } }}
)
// $set the element where "a": 1 does exist
db.test.update(
{ "name": "abc", "config.a": 1 },
{ "$set": { "config.$.b": 2 } }
)
Při první iteraci první příkaz „upsertuje“ dokument a vytvoří pole s položkami. Druhý příkaz nebude odpovídat dokumentu, protože prvek "a" má zadanou hodnotu. Třetí příkaz bude odpovídat dokumentu, ale nezmění jej při operaci zápisu, protože hodnoty se nezměnily.
Pokud nyní změníte vstup na "b": 3
dostanete různé odpovědi, ale požadovaný výsledek:
db.test.update(
{ "name": "abc" },
{ "$setOnInsert": { "config": [{ "a": 1, "b": 3 }] }},
{ "upsert": true }
)
db.test.update(
{ "name": "abc", "config.a": { "$ne": 1 } },
{ "$push": { "config": { "a": 1, "b": 3 } }}
)
db.test.update(
{ "name": "abc", "config.a": 1 },
{ "$set": { "config.$.b": 3 } }
)
Nyní tedy první příkaz odpovídá dokumentu s "name": "abc"
ale nedělá nic, protože jediné platné operace jsou na "insert". Druhý příkaz se neshoduje, protože "a" odpovídá podmínce. Třetí příkaz odpovídá hodnotě „a“ a mění „b“ ve shodném prvku na požadovanou hodnotu.
Následná změna "a" na jinou hodnotu, která v poli neexistuje, umožňuje jak 1, tak 3 nedělat nic, ale druhý příkaz přidá do pole dalšího člena, který udržuje obsah jedinečný pomocí jejich klíčů "a".
Také odeslání výpisu beze změn existujících dat bude mít samozřejmě za následek odpověď, která říká, že se nic nemění na všech účtech.
Tak děláte své operace. Můžete to udělat pomocí "objednaného" Hromadně operace tak, že existuje pouze jeden požadavek a odpověď ze serveru s platnou odpovědí na upraveno nebo vytvořeno.