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

MongoDB $ setDifference

In MongoDB, il $setDifference l'operatore della pipeline di aggregazione accetta due insiemi ed esegue un complemento relativo del secondo insieme rispetto al primo. Restituisce un array contenente gli elementi che esistono solo nel primo set.

$setDifference accetta due argomenti, entrambi possono essere qualsiasi espressione valida purché ciascuno si risolva in un array. $setDifference tratta gli array come insiemi.

Esempio

Supponiamo di avere una raccolta chiamata data con i seguenti documenti:

{ "_id" : 1, "a" : [ 1, 2, 3 ], "b" : [ 1, 2, 3 ] }
{ "_id" : 2, "a" : [ 1, 2, 3 ], "b" : [ 1, 2 ] }
{ "_id" : 3, "a" : [ 1, 2 ], "b" : [ 1, 2, 3 ] }
{ "_id" : 4, "a" : [ 1, 2, 3 ], "b" : [ 3, 4, 5 ] }
{ "_id" : 5, "a" : [ 1, 2, 3 ], "b" : [ 4, 5, 6 ] }

Possiamo applicare il $setDifference operatore contro a e b campi in quei documenti.

Esempio:

db.data.aggregate(
   [
     { $match: { _id: { $in: [ 1, 2, 3, 4, 5 ] } } },
     {
       $project:
          {
            _id: 0,
            a: 1,
            b: 1,
            result: { $setDifference: [ "$a", "$b" ] }
          }
     }
   ]
)

Risultato:

{ "a" : [ 1, 2, 3 ], "b" : [ 1, 2, 3 ], "result" : [ ] }
{ "a" : [ 1, 2, 3 ], "b" : [ 1, 2 ], "result" : [ 3 ] }
{ "a" : [ 1, 2 ], "b" : [ 1, 2, 3 ], "result" : [ ] }
{ "a" : [ 1, 2, 3 ], "b" : [ 3, 4, 5 ], "result" : [ 1, 2 ] }
{ "a" : [ 1, 2, 3 ], "b" : [ 4, 5, 6 ], "result" : [ 1, 2, 3 ] }

Matrici nidificate

Il $setDifference l'operatore non discende in nessun array nidificato. Valuta solo gli array di primo livello.

Supponiamo che la nostra collezione contenga anche i seguenti documenti:

{ "_id" : 6, "a" : [ 1, 2, 3 ], "b" : [ [ 1, 2, 3 ] ] }
{ "_id" : 7, "a" : [ 1, 2, 3 ], "b" : [ [ 1, 2 ], 3 ] }

E applichiamo $setDifference a quei due documenti:

db.data.aggregate(
   [
     { $match: { _id: { $in: [ 6, 7 ] } } },
     {
       $project:
          {
            _id: 0,
            a: 1,
            b: 1,
            result: { $setDifference: [ "$a", "$b" ] }
          }
     }
   ]
)

Risultato:

{ "a" : [ 1, 2, 3 ], "b" : [ [ 1, 2, 3 ] ], "result" : [ 1, 2, 3 ] }
{ "a" : [ 1, 2, 3 ], "b" : [ [ 1, 2 ], 3 ], "result" : [ 1, 2 ] }

Nel primo documento, il b field conteneva un array che conteneva solo un elemento:un altro array. In questo caso, l'array esterno è stato valutato ed è stato riscontrato che non conteneva gli stessi valori che erano nell'array in a .

Tuttavia, se il a field conteneva un array nidificato stesso, potrebbe essere stata una storia diversa.

Supponiamo di avere i seguenti documenti:

{ "_id" : 8, "a" : [ [ 1, 2, 3 ] ], "b" : [ [ 1, 2, 3 ] ] }
{ "_id" : 9, "a" : [ [ 1, 2, 3 ] ], "b" : [ [ 1, 2 ], 3 ] }

E applichiamo $setDifference a quei documenti:

db.data.aggregate(
   [
     { $match: { _id: { $in: [ 8, 9 ] } } },
     {
       $project:
          {
            _id: 0,
            a: 1,
            b: 1,
            result: { $setDifference: [ "$a", "$b" ] }
          }
     }
   ]
)

Risultato:

{ "a" : [ [ 1, 2, 3 ] ], "b" : [ [ 1, 2, 3 ] ], "result" : [ ] }
{ "a" : [ [ 1, 2, 3 ] ], "b" : [ [ 1, 2 ], 3 ], "result" : [ [ 1, 2, 3 ] ] }

Nel primo documento, a corrisponde a b esattamente, e quindi il risultato è un array vuoto.

Nel secondo documento, l'array nidificato in a è diverso dall'array nidificato in b , e così l'intero array nidificato da a viene restituito.

Campi mancanti

Applicazione di $setDifference in un campo inesistente risulta null .

Considera i seguenti documenti:

{ "_id" : 10, "a" : [ 1, 2, 3 ] }
{ "_id" : 11, "b" : [ 1, 2, 3 ] }
{ "_id" : 12 }

Il primo documento non ha un b campo, il secondo documento non ha un a campo e neanche il terzo documento ne ha.

Ecco cosa succede quando applichiamo $setDifference al a e b campi:

db.data.aggregate(
   [
     { $match: { _id: { $in: [ 10, 11, 12 ] } } },
     {
       $project:
          {
            _id: 0,
            a: 1,
            b: 1,
            result: { $setDifference: [ "$a", "$b" ] }
          }
     }
   ]
)

Risultato:

{ "a" : [ 1, 2, 3 ], "result" : null }
{ "b" : [ 1, 2, 3 ], "result" : null }
{ "result" : null }

Tipo di dati errato

Entrambi gli operandi di $setDifference devono essere array. In caso contrario, viene generato un errore.

Supponiamo che la nostra collezione contenga i seguenti documenti:

{ "_id" : 13, "a" : [ 1, 2, 3 ], "b" : 3 }
{ "_id" : 14, "a" : 3, "b" : [ 1, 2, 3 ] }
{ "_id" : 15, "a" : 2, "b" : 3 }

E applichiamo $setDifference a quei documenti:

db.data.aggregate(
   [
     { $match: { _id: { $in: [ 13, 14, 15 ] } } },
     {
       $project:
          {
            _id: 0,
            a: 1,
            b: 1,
            result: { $setDifference: [ "$a", "$b" ] }
          }
     }
   ]
)

Risultato:

uncaught exception: Error: command failed: {
	"ok" : 0,
	"errmsg" : "both operands of $setDifference must be arrays. Second argument is of type: double",
	"code" : 17049,
	"codeName" : "Location17049"
} : aggregate failed :
[email protected]/mongo/shell/utils.js:25:13
[email protected]/mongo/shell/assert.js:18:14
[email protected]/mongo/shell/assert.js:639:17
[email protected]/mongo/shell/assert.js:729:16
[email protected]/mongo/shell/db.js:266:5
[email protected]/mongo/shell/collection.js:1058:12
@(shell):1:1

Valori duplicati

Il $setDifference l'operatore filtra i duplicati nel risultato per generare un array che contiene solo voci univoche. Inoltre, l'ordine degli elementi nell'array di output non è specificato.

Supponiamo di avere i seguenti documenti:

{ "_id" : 16, "a" : [ 1, 1, 2, 2, 3, 3 ], "b" : [ 1, 2, 3 ] }
{ "_id" : 17, "a" : [ 1, 1, 2, 2, 3, 3 ], "b" : [ 1, 2 ] }
{ "_id" : 18, "a" : [ 1, 1, 2, 2, 3, 3 ], "b" : [ ] }
{ "_id" : 19, "a" : [ 3, 2, 1, 2, 3, 1 ], "b" : [ 2, 3, 1 ] }
{ "_id" : 20, "a" : [ 1, 3, 2, 2, 3, 1 ], "b" : [ 2, 1 ] }
{ "_id" : 21, "a" : [ 2, 3, 1, 2, 3, 1 ], "b" : [ ] }

Quindi applichiamo il $setDifference operatore a loro:

db.data.aggregate(
   [
     { $match: { _id: { $in: [ 16, 17, 18, 19, 20, 21 ] } } },
     {
       $project:
          {
            _id: 0,
            a: 1,
            b: 1,
            result: { $setDifference: [ "$a", "$b" ] }
          }
     }
   ]
)

Risultato:

{ "a" : [ 1, 1, 2, 2, 3, 3 ], "b" : [ 1, 2, 3 ], "result" : [ ] }
{ "a" : [ 1, 1, 2, 2, 3, 3 ], "b" : [ 1, 2 ], "result" : [ 3 ] }
{ "a" : [ 1, 1, 2, 2, 3, 3 ], "b" : [ ], "result" : [ 1, 2, 3 ] }
{ "a" : [ 3, 2, 1, 2, 3, 1 ], "b" : [ 2, 3, 1 ], "result" : [ ] }
{ "a" : [ 1, 3, 2, 2, 3, 1 ], "b" : [ 2, 1 ], "result" : [ 3 ] }
{ "a" : [ 2, 3, 1, 2, 3, 1 ], "b" : [ ], "result" : [ 2, 3, 1 ] }