MongoDB ma $push
operator i $addToSet
operator, z których oba robią bardzo podobne rzeczy.
Oba operatory dołączają wartości do istniejącej tablicy. Główna różnica polega na tym, jak radzą sobie z tablicami, które już zawierają wartość, którą próbujesz dołączyć, a także w modyfikatorach, których można użyć.
Różnice
Istniejące wartości | Jeśli wartość już istnieje w tablicy, $push nadal doda wartość (co skutkuje zduplikowanymi wartościami). Jednak $addToSet dołącza tylko wartość, jeśli jeszcze nie istnieje w tablicy. Dlatego jeśli wartość już istnieje, $addToSet nie dołączy go (nic nie zrobi). |
Modyfikatory | $push operator może być używany z dodatkowymi modyfikatorami, takimi jak $sort , $slice i $position , natomiast $addToSet nie może (przynajmniej nie od MongoDB 4.4). |
Istniejące wartości
Załóżmy, że mamy kolekcję z następującymi dokumentami:
db.players.find()
Wynik:
{ "_id" : 1, "scores" : [ 1, 5, 3 ] } { "_id" : 2, "scores" : [ 8, 17, 18 ] } { "_id" : 3, "scores" : [ 3, 5, 5 ] }
Użyjmy $addToSet
aby spróbować dodać wartość do jednej z tablic.
db.players.update(
{ _id: 3 },
{ $addToSet: { scores: 5 } }
)
Wyjście:
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })
To mówi nam, że istniał pasujący dokument (dokument 3), ale nie został zmodyfikowany. Nie został zmodyfikowany, ponieważ wartość, którą próbowaliśmy wstawić (5
) już istnieje w tablicy.
Zajrzyjmy do kolekcji:
db.players.find()
Wynik:
{ "_id" : 1, "scores" : [ 1, 5, 3 ] } { "_id" : 2, "scores" : [ 8, 17, 18 ] } { "_id" : 3, "scores" : [ 3, 5, 5 ] }
Zgodnie z oczekiwaniami, dokument 3 nie został zmieniony.
Spróbujmy $push
zamiast tego:
db.players.update(
{ _id: 3 },
{ $push: { scores: 5 } }
)
Wyjście:
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
Tym razem widzimy, że dokument został zmodyfikowany.
Możemy to zweryfikować, ponownie sprawdzając kolekcję:
db.products.find()
Wynik:
{ "_id" : 1, "scores" : [ 1, 5, 3 ] } { "_id" : 2, "scores" : [ 8, 17, 18 ] } { "_id" : 3, "scores" : [ 3, 5, 5, 5 ] }
Modyfikatory
$push
operator może być używany z modyfikatorami, takimi jak $position
, $sort
i $slice
.
$addToSet
operatora nie można używać z tymi modyfikatorami.
Oto, co się stanie, jeśli spróbuję użyć tych modyfikatorów z $addToSet
:
db.players.update(
{ _id: 3 },
{
$addToSet: {
scores: {
$each: [ 12 ],
$position: 0,
$sort: 1,
$slice: 5
}
}
}
)
Wyjście:
WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0, "writeError" : { "code" : 2, "errmsg" : "Found unexpected fields after $each in $addToSet: { $each: [ 12.0 ], $position: 0.0, $sort: 1.0, $slice: 5.0 }" } })
Komunikat o błędzie informuje nas, że $position
, $sort
i $slice
są nieoczekiwanymi polami (tj. nie powinno ich tam być).
Wypróbujmy te same modyfikatory z $push
:
db.players.update(
{ _id: 3 },
{
$push: {
scores: {
$each: [ 12 ],
$position: 0,
$sort: 1,
$slice: 5
}
}
}
)
Wyjście:
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
Tym razem zadziałało bezbłędnie.
Sprawdź wynik:
db.players.find()
Wynik:
{ "_id" : 1, "scores" : [ 1, 5, 3 ] } { "_id" : 2, "scores" : [ 8, 17, 18 ] } { "_id" : 3, "scores" : [ 3, 5, 5, 5, 12 ] }
Widzimy, że wartość została dodana. Mimo że określiliśmy $position: 0
, określiliśmy również $sort: 1
, co oznacza, że tablica została posortowana po jej umieszczeniu.
Określiliśmy również $slice: 5
, co ograniczało tablicę do zaledwie 5 elementów (co jak się okazało, było dokładnie tym, ile elementów i tak było w tablicy).