Proces tutaj jest naprawdę dość prosty, różni się tylko w zależności od tego, gdzie chcesz „znaleźć lub utworzyć” elementy w tablicy.
Po pierwsze, zakładając, że elementy dla każdego klucza są już na miejscu, wtedy prostym przypadkiem jest zapytanie o element i aktualizacja indeksem zwróconym przez pozycyjny $
operator:
db.collection.update(
{
"_id": docId,
"attrs": { "$elemMatch": { "key": "A1", "type": "T1" } }
}
{ "$set": { "attrs.$.value": "20" }
)
To zmodyfikuje tylko dopasowany element bez wpływu na inne.
W drugim przypadku, gdy wymagane jest „znajdź lub utwórz”, a dany klucz może nie istnieć, użyj „dwóch” instrukcji aktualizacji. Ale Interfejs API operacji zbiorczych pozwala to zrobić w jednym żądaniu do serwera z jedną odpowiedzią:
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();
Podstawowa logika polega na tym, że najpierw podjęta jest próba aktualizacji, aby dopasować element z wymaganymi wartościami, tak jak wcześniej. Inne warunki sprawdzają, gdzie element w ogóle nie został znaleziony, odwracając logikę dopasowania za pomocą $not
.
W przypadku, gdy element tablicy nie został znaleziony, nowy można dodać za pomocą $push
.
Powinienem naprawdę dodać, że ponieważ szukamy tutaj dopasowań negatywnych, zawsze dobrym pomysłem jest dopasowanie „dokumentu”, który zamierzasz zaktualizować, za pomocą jakiegoś unikalnego identyfikatora, takiego jak _id
klucz. Chociaż jest to możliwe w przypadku aktualizacji „multi”, musisz uważać na to, co robisz.
Tak więc w przypadku uruchomienia procesu „znajdź lub utwórz” element, który nie został dopasowany, zostanie poprawnie dodany do tablicy, bez ingerencji w inne elementy, również poprzednia aktualizacja dla oczekiwanego dopasowania jest stosowana w ten sam sposób:
{
"_id" : ObjectId("55b570f339db998cde23369d"),
"attrs" : [
{
"key" : "A1",
"type" : "T1",
"value" : "20"
},
{
"key" : "A2",
"type" : "T2",
"value" : "14"
},
{
"key" : "A1",
"type" : "T2",
"value" : "30"
}
]
}
Jest to prosty wzorzec do naśladowania i oczywiście operacje zbiorcze usuwają wszelkie obciążenia związane z wysyłaniem i odbieraniem wielu żądań do iz serwera. Wszystko to szczęśliwie działa bez ingerencji w inne elementy, które mogą lub nie mogą istnieć.
Poza tym istnieją dodatkowe korzyści z utrzymywania danych w tablicy w celu łatwego wykonywania zapytań i analiz, obsługiwane przez standardowe operatory, bez konieczności powracania do przetwarzania przez serwer JavaScript w celu przechodzenia przez elementy.