MongoDB ha un $push operatore e un $addToSet operatore, entrambi i quali fanno una cosa molto simile.
Entrambi gli operatori aggiungono valori a una matrice esistente. La differenza principale è nel modo in cui gestiscono gli array che contengono già il valore che stai cercando di aggiungere e anche nei modificatori che possono essere utilizzati.
Le differenze
| Valori esistenti | Se il valore esiste già nell'array, $push aggiungerà comunque il valore (con conseguente duplicazione dei valori). Tuttavia, $addToSet aggiunge il valore solo se non esiste già nell'array. Pertanto, se il valore esiste già, $addToSet non lo aggiungerà (non farà nulla). |
| Modificatori | Il $push può essere utilizzato con modificatori aggiuntivi, come $sort , $slice e $position , mentre $addToSet non può (almeno, non a partire da MongoDB 4.4). |
Valori esistenti
Supponiamo di avere una collezione con i seguenti documenti:
db.players.find() Risultato:
{ "_id" : 1, "scores" : [ 1, 5, 3 ] }
{ "_id" : 2, "scores" : [ 8, 17, 18 ] }
{ "_id" : 3, "scores" : [ 3, 5, 5 ] }
Usiamo $addToSet per provare ad aggiungere un valore a uno degli array.
db.players.update(
{ _id: 3 },
{ $addToSet: { scores: 5 } }
) Uscita:
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })
Questo ci dice che c'era un documento corrispondente (documento 3), ma non è stato modificato. Non è stato modificato perché il valore che abbiamo provato a inserire (5 ) esiste già nell'array.
Diamo un'occhiata alla collezione:
db.players.find() Risultato:
{ "_id" : 1, "scores" : [ 1, 5, 3 ] }
{ "_id" : 2, "scores" : [ 8, 17, 18 ] }
{ "_id" : 3, "scores" : [ 3, 5, 5 ] } Come previsto, il documento 3 non è stato modificato.
Proviamo $push invece:
db.players.update(
{ _id: 3 },
{ $push: { scores: 5 } }
) Uscita:
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) Questa volta vediamo che il documento è stato modificato.
Possiamo verificarlo controllando di nuovo la collezione:
db.products.find() Risultato:
{ "_id" : 1, "scores" : [ 1, 5, 3 ] }
{ "_id" : 2, "scores" : [ 8, 17, 18 ] }
{ "_id" : 3, "scores" : [ 3, 5, 5, 5 ] } Modificatori
Il $push può essere utilizzato con modificatori come $position , $sort e $slice .
Il $addToSet l'operatore non può essere utilizzato con questi modificatori.
Ecco cosa succede se provo a utilizzare questi modificatori con $addToSet :
db.players.update(
{ _id: 3 },
{
$addToSet: {
scores: {
$each: [ 12 ],
$position: 0,
$sort: 1,
$slice: 5
}
}
}
) Uscita:
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 }"
}
})
Il messaggio di errore ci dice che il $position , $sort e $slice sono campi imprevisti (cioè non dovrebbero essere presenti).
Proviamo gli stessi modificatori con $push :
db.players.update(
{ _id: 3 },
{
$push: {
scores: {
$each: [ 12 ],
$position: 0,
$sort: 1,
$slice: 5
}
}
}
) Uscita:
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) Questa volta ha funzionato senza errori.
Verifica il risultato:
db.players.find() Risultato:
{ "_id" : 1, "scores" : [ 1, 5, 3 ] }
{ "_id" : 2, "scores" : [ 8, 17, 18 ] }
{ "_id" : 3, "scores" : [ 3, 5, 5, 5, 12 ] }
Possiamo vedere che il valore è stato aggiunto. Anche se abbiamo specificato $position: 0 , abbiamo anche specificato $sort: 1 , il che significa che l'array è stato ordinato dopo averlo posizionato.
Abbiamo anche specificato $slice: 5 , che limitava l'array a soli 5 elementi (che, come si è scoperto, erano comunque esattamente quanti elementi c'erano nell'array).