Искате .bulkWrite()
за това. Това всъщност не е една операция, така че искате да изпратите няколко операции в една заявка. По същество се опитайте да напишете актуализацията с $set
където съществуват данни или $push
новите данни, когато не съществуват:
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" } }
}
}}
])
Положителният случай е просто стойността и $neкод>
"отрича" съответствието на равенството, което означава, че елементът не съществува. Разбира се, позиционният $
оператор
се използва с $set
където става
Като се имат предвид данните, само една от операциите действително ще съответства и ще се приложи като актуализация, въпреки че две операции са изпратени в „партида“.
Ако искате "upserts" и за целия документ, тогава трябва да добавите друга операция в края на това. Обърнете внимание, че не можете да приложите „upsert“ като опция към нито един от другите изрази, особено към $ne
защото това би създало нов документ, където елементът от масива не съществува, а не само _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
е основната помощ тук, освен че последната операция е единствената, маркирана като "upsert"
. Тази комбинация гарантира, че там, където е намерен основният „документ“, всъщност нищо не се случва, но когато не бъде намерен, се добавя новият елемент от масива.
Като странична бележка, силно препоръчвам цифровите стойности да се съхраняват като числови, а не като низове. Не само спестява място в повечето случаи, но е и много по-полезно по този начин.