MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

MongoDB $ push vs $ addToSet:qual è la differenza?

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).