MongoDB har en $push
operator och en $addToSet
operatör, som båda gör en mycket liknande sak.
Båda operatorerna lägger till värden till en befintlig matris. Den största skillnaden ligger i hur de hanterar arrayer som redan innehåller värdet du försöker lägga till, och även i modifierarna som kan användas.
Skillnaderna
Befintliga värden | Om värdet redan finns i arrayen, $push kommer fortfarande att lägga till värdet (vilket resulterar i dubbletter av värden). Men $addToSet lägger bara till värdet om det inte redan finns i arrayen. Därför, om värdet redan finns, $addToSet kommer inte att lägga till det (det gör ingenting). |
Modifierare | $push operatorn kan användas med ytterligare modifierare, såsom $sort , $slice och $position , medan $addToSet kan inte (åtminstone inte från och med MongoDB 4.4). |
Befintliga värden
Anta att vi har en samling med följande dokument:
db.players.find()
Resultat:
{ "_id" : 1, "scores" : [ 1, 5, 3 ] } { "_id" : 2, "scores" : [ 8, 17, 18 ] } { "_id" : 3, "scores" : [ 3, 5, 5 ] }
Låt oss använda $addToSet
för att försöka lägga till ett värde till en av arrayerna.
db.players.update(
{ _id: 3 },
{ $addToSet: { scores: 5 } }
)
Utdata:
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })
Detta berättar för oss att det fanns ett matchande dokument (dokument 3), men det ändrades inte. Det ändrades inte eftersom värdet vi försökte infoga (5
) finns redan i arrayen.
Låt oss titta i samlingen:
db.players.find()
Resultat:
{ "_id" : 1, "scores" : [ 1, 5, 3 ] } { "_id" : 2, "scores" : [ 8, 17, 18 ] } { "_id" : 3, "scores" : [ 3, 5, 5 ] }
Som väntat har dokument 3 inte ändrats.
Låt oss prova $push
istället:
db.players.update(
{ _id: 3 },
{ $push: { scores: 5 } }
)
Utdata:
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
Den här gången ser vi att dokumentet har ändrats.
Vi kan verifiera detta genom att kontrollera samlingen igen:
db.products.find()
Resultat:
{ "_id" : 1, "scores" : [ 1, 5, 3 ] } { "_id" : 2, "scores" : [ 8, 17, 18 ] } { "_id" : 3, "scores" : [ 3, 5, 5, 5 ] }
Modifierare
$push
operatorn kan användas med modifierare som $position
, $sort
och $slice
.
$addToSet
operatorn kan inte användas med dessa modifierare.
Här är vad som händer om jag försöker använda dessa modifierare med $addToSet
:
db.players.update(
{ _id: 3 },
{
$addToSet: {
scores: {
$each: [ 12 ],
$position: 0,
$sort: 1,
$slice: 5
}
}
}
)
Utdata:
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 }" } })
Felmeddelandet talar om för oss att $position
, $sort
och $slice
är oväntade fält (dvs. de borde inte finnas där).
Låt oss prova samma modifierare med $push
:
db.players.update(
{ _id: 3 },
{
$push: {
scores: {
$each: [ 12 ],
$position: 0,
$sort: 1,
$slice: 5
}
}
}
)
Utdata:
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
Den här gången fungerade det felfritt.
Verifiera resultatet:
db.players.find()
Resultat:
{ "_id" : 1, "scores" : [ 1, 5, 3 ] } { "_id" : 2, "scores" : [ 8, 17, 18 ] } { "_id" : 3, "scores" : [ 3, 5, 5, 5, 12 ] }
Vi kan se att värdet har lagts till. Även om vi angav $position: 0
, vi angav också $sort: 1
, vilket betyder att arrayen sorterades efter att vi placerade den.
Vi angav också $slice: 5
, vilket begränsade arrayen till bara 5 element (vilket som det visade sig var exakt hur många element som fanns i arrayen ändå).