MongoDB heeft een $push
operator en een $addToSet
operator, die beide ongeveer hetzelfde doen.
Beide operators voegen waarden toe aan een bestaande array. Het belangrijkste verschil is hoe ze omgaan met arrays die al de waarde bevatten die u probeert toe te voegen, en ook in de modifiers die kunnen worden gebruikt.
De verschillen
Bestaande waarden | Als de waarde al in de array bestaat, $push zal de waarde nog steeds toevoegen (resulterend in dubbele waarden). Echter, $addToSet voegt de waarde alleen toe als deze nog niet in de array bestaat. Daarom, als de waarde al bestaat, $addToSet zal het niet toevoegen (het zal niets doen). |
Modificaties | De $push operator kan worden gebruikt met extra modificaties, zoals $sort , $slice , en $position , terwijl $addToSet kan niet (tenminste, niet vanaf MongoDB 4.4). |
Bestaande waarden
Stel we hebben een collectie met de volgende documenten:
db.players.find()
Resultaat:
{ "_id" : 1, "scores" : [ 1, 5, 3 ] } { "_id" : 2, "scores" : [ 8, 17, 18 ] } { "_id" : 3, "scores" : [ 3, 5, 5 ] }
Laten we $addToSet
gebruiken om te proberen een waarde aan een van de arrays toe te voegen.
db.players.update(
{ _id: 3 },
{ $addToSet: { scores: 5 } }
)
Uitgang:
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })
Dit vertelt ons dat er een overeenkomend document was (document 3), maar dat het niet is gewijzigd. Het is niet gewijzigd omdat de waarde die we probeerden in te voegen (5
) bestaat al in de array.
Laten we eens in de collectie kijken:
db.players.find()
Resultaat:
{ "_id" : 1, "scores" : [ 1, 5, 3 ] } { "_id" : 2, "scores" : [ 8, 17, 18 ] } { "_id" : 3, "scores" : [ 3, 5, 5 ] }
Zoals verwacht is document 3 niet gewijzigd.
Laten we $push
proberen in plaats daarvan:
db.players.update(
{ _id: 3 },
{ $push: { scores: 5 } }
)
Uitgang:
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
Deze keer zien we dat het document is gewijzigd.
We kunnen dit verifiëren door de collectie opnieuw te controleren:
db.products.find()
Resultaat:
{ "_id" : 1, "scores" : [ 1, 5, 3 ] } { "_id" : 2, "scores" : [ 8, 17, 18 ] } { "_id" : 3, "scores" : [ 3, 5, 5, 5 ] }
Modificaties
De $push
operator kan worden gebruikt met modifiers zoals $position
, $sort
, en $slice
.
De $addToSet
operator kan niet worden gebruikt met deze modifiers.
Dit is wat er gebeurt als ik deze modifiers probeer te gebruiken met $addToSet
:
db.players.update(
{ _id: 3 },
{
$addToSet: {
scores: {
$each: [ 12 ],
$position: 0,
$sort: 1,
$slice: 5
}
}
}
)
Uitgang:
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 }" } })
De foutmelding vertelt ons dat de $position
, $sort
, en $slice
zijn onverwachte velden (d.w.z. ze zouden er niet moeten zijn).
Laten we dezelfde modifiers proberen met $push
:
db.players.update(
{ _id: 3 },
{
$push: {
scores: {
$each: [ 12 ],
$position: 0,
$sort: 1,
$slice: 5
}
}
}
)
Uitgang:
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
Deze keer werkte het zonder fouten.
Controleer het resultaat:
db.players.find()
Resultaat:
{ "_id" : 1, "scores" : [ 1, 5, 3 ] } { "_id" : 2, "scores" : [ 8, 17, 18 ] } { "_id" : 3, "scores" : [ 3, 5, 5, 5, 12 ] }
We kunnen zien dat de waarde is toegevoegd. Ook al hebben we $position: 0
specified gespecificeerd , we hebben ook $sort: 1
. opgegeven , wat betekent dat de array is gesorteerd nadat we deze hebben gepositioneerd.
We hebben ook $slice: 5
. gespecificeerd , die de array beperkte tot slechts 5 elementen (wat uiteindelijk precies het aantal elementen in de array was).