Załóżmy, że mamy następującą kolekcję, o której mam kilka pytań:
{
"_id" : ObjectId("4faaba123412d654fe83hg876"),
"user_id" : 123456,
"total" : 100,
"items" : [
{
"item_name" : "my_item_one",
"price" : 20
},
{
"item_name" : "my_item_two",
"price" : 50
},
{
"item_name" : "my_item_three",
"price" : 30
}
]
}
1 - Chcę podnieść cenę za „item_name”: „my_item_two”, a jeśli nie istnieje , należy go dołączyć do tablicy „items”.
2 - Jak mogę zaktualizować dwa pola jednocześnie. Na przykład podnieś cenę „my_item_three” i jednocześnie zwiększ „total” (o tej samej wartości).
Wolę to robić po stronie MongoDB, w przeciwnym razie muszę załadować dokument po stronie klienta (Python) i zbudować zaktualizowany dokument i zastąpić go istniejącym w MongoDB.
AKTUALIZACJA Oto, co próbowałem i działa dobrze JEŚLI Obiekt istnieje :
db.test_invoice.update({user_id : 123456 , "items.item_name":"my_item_one"} , {$inc: {"items.$.price": 10}})
Ale jeśli klucz nie istnieje, nic nie robi. Aktualizuje także tylko zagnieżdżony obiekt. Za pomocą tego polecenia nie można również zaktualizować pola „suma”.
Odpowiedzi:
W przypadku pytania nr 1 podzielmy je na dwie części. Najpierw zwiększ każdy dokument, który ma „item.item_name” równy „my_item_two”. W tym celu musisz użyć operatora pozycyjnego „$”. Coś jak:
Zauważ, że zwiększy to tylko pierwszy dopasowany dokument podrzędny w dowolnej tablicy (więc jeśli masz inny dokument w tablicy o nazwie „item_name” równej „my_item_two”, nie zostanie on zwiększony). Ale to może być to, czego chcesz.
Druga część jest trudniejsza. Możemy wypchnąć nowy element do tablicy bez „my_item_two” w następujący sposób:
Na pytanie nr 2 odpowiedź jest łatwiejsza. Aby zwiększyć sumę i cenę item_three w dowolnym dokumencie zawierającym „my_item_three”, możesz użyć operatora $ inc na wielu polach jednocześnie. Coś jak:
źródło
Nie ma takiej możliwości w pojedynczym zapytaniu. Musisz przeszukać dokument przy pierwszym zapytaniu:
Jeśli dokument istnieje:
Jeszcze
Nie trzeba dodawać warunku
{$ne : "my_item_two" }
.Również w środowisku wielowątkowym należy uważać, aby tylko jeden wątek mógł wykonać drugi (wstaw przypadek, jeśli dokument nie został znaleziony) naraz, w przeciwnym razie zostaną wstawione duplikaty osadzonych dokumentów.
źródło
Możemy użyć
$set
operatora, aby zaktualizować zagnieżdżoną tablicę wewnątrz obiektu, aby zaktualizować wartośćźródło