Chcete .bulkWrite()
pro tohle. Toto ve skutečnosti není jedna operace, takže chcete odeslat více operací v jedné žádosti. V podstatě se pokuste zapsat aktualizaci pomocí $set
kde data existují nebo $push
nová data tam, kde neexistují:
db.collection.bulkWrite([
{ "updateOne": {
"filter": { "_id": "1", "option.weight": "10" },
"update": {
"$set": { "option.$.price": "30" }
}
}},
{ "updateOne": {
"filter": { "_id": "1", "option.weight": { "$ne": "10" } },
"update": {
"$push": { "option": { "weight": "10", "price": "30" } }
}
}}
])
Kladný případ je jednoduše hodnota a $ne
"neguje" shodu rovnosti, což znamená, že položka neexistuje. Samozřejmě poziční $
operátor
se používá s $set
kde to dělá
Vzhledem k těmto datům se bude ve skutečnosti shodovat pouze jedna z operací a použije se jako aktualizace, přestože dvě operace byly odeslány v „dávce“.
Pokud chcete "upserts" i pro celý dokument, pak je třeba přidat na konec další operaci. Všimněte si, že nemůžete použít "upsert" jako možnost na žádný z ostatních příkazů, zejména na $ne
protože to by vytvořilo nový dokument, kde položka pole neexistuje, nejen _id
:
db.collection.bulkWrite([
{ "updateOne": {
"filter": { "_id": "1", "option.weight": "10" },
"update": {
"$set": { "option.$.price": "30" }
}
}},
{ "updateOne": {
"filter": { "_id": "1", "option.weight": { "$ne": "10" } },
"update": {
"$push": { "option": { "weight": "10", "price": "30" } }
}
}},
{ "updateOne": {
"filter": { "_id": 1 },
"update": {
"$setOnInsert": {
"option": [
{ "weight": "10", "price": "30" }
]
}
},
"upsert": true
}}
])
$setOnInsert
je zde hlavní nápověda kromě toho, že poslední operace je jediná označená jako "upsert"
. Tato kombinace zajišťuje, že tam, kde se najde primární „dokument“, se ve skutečnosti nic nestane, ale když nebude nalezen, přidá se nová položka pole.
Jako vedlejší poznámku bych důrazně doporučil ukládat číselné hodnoty ve skutečnosti jako číselné spíše než řetězce. Ve většině případů to nejen šetří místo, ale je to také mnohem užitečnější.