Процесът тук наистина е доста прост, варира само в зависимост от това къде искате да „намерите или създадете“ елементите в масива.
Първо, ако приемем, че елементите за всеки ключ вече са на мястото си, тогава простият случай е да се направи заявка за елемента и да се актуализира с индекса, върнат чрез позиционен $
оператор:
db.collection.update(
{
"_id": docId,
"attrs": { "$elemMatch": { "key": "A1", "type": "T1" } }
}
{ "$set": { "attrs.$.value": "20" }
)
Това ще промени само съвпадащия елемент, без да засяга другите.
Във втория случай, когато се изисква „намиране или създаване“ и конкретният ключ може да не съществува, тогава използвате „два“ израза за актуализиране. Но API за групови операции ви позволява да направите това в една заявка към сървъра с един отговор:
var bulk = db.collection.initializeOrderedBulkOp();
// Try to update where exists
bulk.find({
"_id": docId,
"attrs": { "$elemMatch": { "key": "A1", "type": "T2" } }
}).updateOne({
"$set": { "attrs.$.value": "30" }
});
// Try to add where does noes not exist
bulk.find({
"_id": docId,
"attrs": { "$not": { "$elemMatch": { "key": "A1", "type": "T2" } } }
}).updateOne({
"$push": { "attrs": { "key": "A1", "type": "T2", "value": "30" } }
});
bulk.execute();
Основната логика е, че първо се прави опит за актуализиране, за да се съпостави елемент с изискваните стойности, точно както беше направено преди. Другото условие тества къде елементът изобщо не е намерен чрез обръщане на логиката на съвпадението с $not
.
В случай, че елементът на масива не е намерен, нов е валиден за добавяне чрез $push
.
Наистина трябва да добавя, че тъй като ние специално търсим отрицателни съвпадения тук, винаги е добра идея да съответствате на „документа“, който възнамерявате да актуализирате, чрез някакъв уникален идентификатор, като например _id
ключ. Въпреки че е възможно с "много" актуализации, трябва да внимавате какво правите.
Така че в случай на стартиране на процеса „намиране или създаване“, тогава елементът, който не е съвпаднал, се добавя към масива правилно, без да пречи на други елементи, също така предишната актуализация за очаквано съвпадение се прилага по същия начин:
{
"_id" : ObjectId("55b570f339db998cde23369d"),
"attrs" : [
{
"key" : "A1",
"type" : "T1",
"value" : "20"
},
{
"key" : "A2",
"type" : "T2",
"value" : "14"
},
{
"key" : "A1",
"type" : "T2",
"value" : "30"
}
]
}
Това е прост модел, който трябва да следвате и, разбира се, груповите операции тук премахват всички допълнителни разходи чрез изпращане и получаване на множество заявки към и от сървъра. Всичко това успешно работи, без да пречи на други елементи, които могат или не могат да съществуват.
Освен това, има допълнителни предимства от запазването на данните в масив за лесна заявка и анализ, както се поддържа от стандартните оператори, без да е необходимо да се връщате към обработка на JavaScript сървър, за да преминете през елементите.