MongoDB har en $push
operator og en $addToSet
operatør, som begge gør en meget lignende ting.
Begge operatorer tilføjer værdier til en eksisterende matrix. Den største forskel er i, hvordan de håndterer arrays, der allerede indeholder den værdi, du forsøger at tilføje, og også i de modifikatorer, der kan bruges.
Forskellene
Eksisterende værdier | Hvis værdien allerede findes i arrayet, $push vil stadig tilføje værdien (hvilket resulterer i duplikerede værdier). Dog $addToSet tilføjer kun værdien, hvis den ikke allerede findes i arrayet. Derfor, hvis værdien allerede eksisterer, $addToSet vil ikke tilføje det (det vil ikke gøre noget). |
Modifiers | $push operator kan bruges med yderligere modifikatorer, såsom $sort , $slice , og $position , hvorimod $addToSet kan ikke (i hvert fald ikke fra MongoDB 4.4). |
Eksisterende værdier
Antag, at vi har en samling med følgende dokumenter:
db.players.find()
Resultat:
{ "_id" : 1, "scores" : [ 1, 5, 3 ] } { "_id" : 2, "scores" : [ 8, 17, 18 ] } { "_id" : 3, "scores" : [ 3, 5, 5 ] }
Lad os bruge $addToSet
for at prøve at tilføje en værdi til et af arrays.
db.players.update(
{ _id: 3 },
{ $addToSet: { scores: 5 } }
)
Output:
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })
Dette fortæller os, at der var et matchende dokument (dokument 3), men det blev ikke ændret. Den blev ikke ændret, fordi den værdi, vi forsøgte at indsætte (5
) findes allerede i arrayet.
Lad os se 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 forventet er dokument 3 ikke blevet ændret.
Lad os prøve $push
i stedet:
db.players.update(
{ _id: 3 },
{ $push: { scores: 5 } }
)
Output:
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
Denne gang ser vi, at dokumentet blev ændret.
Vi kan bekræfte dette ved at tjekke 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 ] }
Modifiers
$push
operator kan bruges med modifikatorer såsom $position
, $sort
, og $slice
.
$addToSet
operator kan ikke bruges med disse modifikatorer.
Her er hvad der sker, hvis jeg prøver at bruge disse modifikatorer med $addToSet
:
db.players.update(
{ _id: 3 },
{
$addToSet: {
scores: {
$each: [ 12 ],
$position: 0,
$sort: 1,
$slice: 5
}
}
}
)
Output:
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 }" } })
Fejlmeddelelsen fortæller os, at $position
, $sort
, og $slice
er uventede felter (dvs. de burde ikke være der).
Lad os prøve de samme modifikatorer med $push
:
db.players.update(
{ _id: 3 },
{
$push: {
scores: {
$each: [ 12 ],
$position: 0,
$sort: 1,
$slice: 5
}
}
}
)
Output:
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
Denne gang virkede det uden fejl.
Bekræft 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, at værdien er blevet tilføjet. Selvom vi specificerede $position: 0
, vi specificerede også $sort: 1
, hvilket betyder, at arrayet blev sorteret efter vi havde placeret det.
Vi specificerede også $slice: 5
, som begrænsede arrayet til kun 5 elementer (hvilket som det viste sig, var præcis hvor mange elementer der var i arrayet alligevel).