MongoDB má $push
operátor a $addToSet
operátor, oba dělají velmi podobnou věc.
Oba operátory připojí hodnoty k existujícímu poli. Hlavní rozdíl je v tom, jak nakládají s poli, která již obsahují hodnotu, kterou se pokoušíte připojit, a také v modifikátorech, které lze použít.
Rozdíly
Stávající hodnoty | Pokud již hodnota v poli existuje, $push stále připojí hodnotu (výsledkem budou duplicitní hodnoty). Nicméně $addToSet pouze připojí hodnotu, pokud již v poli neexistuje. Pokud tedy hodnota již existuje, $addToSet ji nepřipojí (neudělá nic). |
Modifikátory | $push operátor lze použít s dalšími modifikátory, jako je $sort , $slice a $position , zatímco $addToSet nemůže (alespoň ne od MongoDB 4.4). |
Stávající hodnoty
Předpokládejme, že máme sbírku s následujícími dokumenty:
db.players.find()
Výsledek:
{ "_id" : 1, "scores" : [ 1, 5, 3 ] } { "_id" : 2, "scores" : [ 8, 17, 18 ] } { "_id" : 3, "scores" : [ 3, 5, 5 ] }
Použijme $addToSet
pokusit se připojit hodnotu k jednomu z polí.
db.players.update(
{ _id: 3 },
{ $addToSet: { scores: 5 } }
)
Výstup:
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })
To nám říká, že existoval odpovídající dokument (dokument 3), ale nebyl upraven. Nebyla upravena, protože hodnota, kterou jsme se pokusili vložit (5
) již v poli existuje.
Podívejme se do sbírky:
db.players.find()
Výsledek:
{ "_id" : 1, "scores" : [ 1, 5, 3 ] } { "_id" : 2, "scores" : [ 8, 17, 18 ] } { "_id" : 3, "scores" : [ 3, 5, 5 ] }
Podle očekávání se dokument 3 nezměnil.
Zkusme $push
místo toho:
db.players.update(
{ _id: 3 },
{ $push: { scores: 5 } }
)
Výstup:
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
Tentokrát vidíme, že dokument byl upraven.
Můžeme to ověřit opětovnou kontrolou sbírky:
db.products.find()
Výsledek:
{ "_id" : 1, "scores" : [ 1, 5, 3 ] } { "_id" : 2, "scores" : [ 8, 17, 18 ] } { "_id" : 3, "scores" : [ 3, 5, 5, 5 ] }
Modifikátory
$push
operátor lze použít s modifikátory, jako je $position
, $sort
a $slice
.
$addToSet
operátor nelze použít s těmito modifikátory.
Zde je to, co se stane, když se pokusím použít tyto modifikátory s $addToSet
:
db.players.update(
{ _id: 3 },
{
$addToSet: {
scores: {
$each: [ 12 ],
$position: 0,
$sort: 1,
$slice: 5
}
}
}
)
Výstup:
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 }" } })
Chybová zpráva nám říká, že $position
, $sort
a $slice
jsou neočekávaná pole (tj. neměla by tam být).
Zkusme stejné modifikátory s $push
:
db.players.update(
{ _id: 3 },
{
$push: {
scores: {
$each: [ 12 ],
$position: 0,
$sort: 1,
$slice: 5
}
}
}
)
Výstup:
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
Tentokrát to fungovalo bez chyby.
Ověřte výsledek:
db.players.find()
Výsledek:
{ "_id" : 1, "scores" : [ 1, 5, 3 ] } { "_id" : 2, "scores" : [ 8, 17, 18 ] } { "_id" : 3, "scores" : [ 3, 5, 5, 5, 12 ] }
Vidíme, že hodnota byla připojena. I když jsme zadali $position: 0
, také jsme zadali $sort: 1
, což znamená, že pole bylo seřazeno poté, co jsme jej umístili.
Také jsme zadali $slice: 5
, který omezil pole na pouhých 5 prvků (což, jak se ukázalo, bylo přesně tolik prvků v poli stejně).