Właściwie robienie tego, co wydaje się, że robisz, nie jest pojedynczą operacją, ale przejdę przez części wymagane w tym celu lub w inny sposób omówię inne możliwe sytuacje.
To, czego szukasz, to częściowo pozycyjny $
operator. Potrzebujesz części zapytania, aby „znaleźć” żądany element tablicy.
db.products.update(
{
"_id": ObjectId("536c55bf9c8fb24c21000095"),
"recentviews.viewedby": "abc"
},
{
"$set": {
"recentviews.$.vieweddate": ISODate("2014-05-09T04:12:47.907Z")
}
}
)
Więc $
oznacza dopasowaną pozycję w tablicy, aby część aktualizacyjna wiedziała, który element w tablicy ma zostać zaktualizowany. Możesz uzyskać dostęp do poszczególnych pól dokumentu w tablicy lub po prostu określić cały dokument do aktualizacji w tej pozycji.
db.products.update(
{
"_id": ObjectId("536c55bf9c8fb24c21000095"),
"recentviews.viewedby": "abc"
},
{
"$set": {
"recentviews.$": {
"viewedby": "abc",
"vieweddate": ISODate("2014-05-09T04:12:47.907Z")
}
}
)
Jeśli pola w rzeczywistości się nie zmieniają i chcesz tylko wstawić nowy element tablicy, jeśli dokładnie taki sam nie istnieje, możesz użyć $addToSet
db.products.update(
{
"_id": ObjectId("536c55bf9c8fb24c21000095"),
"recentviews.viewedby": "abc"
},
{
$addToSet:{
"recentviews": {
"viewedby": "abc",
"vieweddate": ISODate("2014-05-09T04:12:47.907Z")
}
}
)
Jeśli jednak szukasz tylko „przepychania” do tablicy przez pojedynczą wartość klucza, jeśli taka nie istnieje, musisz wykonać trochę więcej ręcznej obsługi, najpierw sprawdzając, czy element w tablicy istnieje, a następnie wykonując $push
oświadczenie, w którym tak nie jest.
Możesz uzyskać pomoc od metod mangusty w zrobieniu tego, śledząc liczbę dokumentów, których dotyczy aktualizacja:
Product.update(
{
"_id": ObjectId("536c55bf9c8fb24c21000095"),
"recentviews.viewedby": "abc"
},
{
"$set": {
"recentviews.$": {
"viewedby": "abc",
"vieweddate": ISODate("2014-05-09T04:12:47.907Z")
}
},
function(err,numAffected) {
if (numAffected == 0) {
// Document not updated so you can push onto the array
Product.update(
{
"_id": ObjectId("536c55bf9c8fb24c21000095")
},
{
"$push": {
"recentviews": {
"viewedby": "abc",
"vieweddate": ISODate("2014-05-09T04:12:47.907Z")
}
}
},
function(err,numAffected) {
}
);
}
}
);
Jedynym słowem przestrogi jest tutaj niewielka zmiana implementacji w komunikatach writeConcern z MongoDB 2.6 do wcześniejszych wersji. Nie mam pewności, w jaki sposób interfejs API mongoose faktycznie implementuje zwrot numAffected
argument w wywołaniu zwrotnym różnica może coś znaczyć.
W poprzednich wersjach, nawet jeśli dane, które wysłałeś w początkowej aktualizacji dokładnie pasowały do istniejącego elementu i nie była wymagana żadna rzeczywista zmiana, „zmodyfikowana” kwota byłaby zwracana jako 1
nawet jeśli nic nie zostało zaktualizowane.
Od MongoDB 2.6 odpowiedź dotycząca zapisu zawiera dwie części. Jedna część pokazuje zmodyfikowany dokument, a druga pokazuje dopasowanie. Tak więc, podczas gdy dopasowanie zostanie zwrócone przez część zapytania pasującą do istniejącego elementu, rzeczywista liczba zmodyfikowanych dokumentów zostanie zwrócona jako 0
jeśli w rzeczywistości nie była wymagana żadna zmiana.
Tak więc w zależności od tego, jak faktycznie zaimplementowano numer zwrotu w manguście, bezpieczniej może być użyć $addToSet
operatora na tej wewnętrznej aktualizacji, aby upewnić się, że jeśli przyczyną braku dokumentów, których dotyczy zero, nie było tylko to, że ten element już istniał.