sql >> Base de Datos >  >> NoSQL >> MongoDB

MongoDB $establecerdiferencia

En MongoDB, el $setDifference El operador de tubería de agregación acepta dos conjuntos y realiza un complemento relativo del segundo conjunto en relación con el primero. Devuelve una matriz que contiene los elementos que solo existen en el primer conjunto.

$setDifference acepta dos argumentos, los cuales pueden ser cualquier expresión válida siempre que cada uno se resuelva en una matriz. $setDifference trata las matrices como conjuntos.

Ejemplo

Supongamos que tenemos una colección llamada data con los siguientes documentos:

{ "_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 ] }

Podemos aplicar el $setDifference operador contra el a y b campos en esos documentos.

Ejemplo:

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

Resultado:

{ "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 ] }

Matrices anidadas

El $setDifference El operador no desciende a ninguna matriz anidada. Solo evalúa matrices de nivel superior.

Supongamos que nuestra colección también contiene los siguientes documentos:

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

Y aplicamos $setDifference a esos dos documentos:

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

Resultado:

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

En el primer documento, el b El campo contenía una matriz que contenía solo un elemento:otra matriz. En este caso, se evaluó la matriz externa y se encontró que no contenía los mismos valores que estaban en la matriz en a .

Sin embargo, si el a campo hubiera contenido una matriz anidada, podría haber sido una historia diferente.

Supongamos que tenemos los siguientes documentos:

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

Y aplicamos $setDifference a esos documentos:

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

Resultado:

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

En el primer documento, a coincide con b exactamente, por lo que el resultado es una matriz vacía.

En el segundo documento, la matriz anidada en a es diferente a la matriz anidada en b , y así toda la matriz anidada de a es devuelto.

Campos faltantes

Aplicando $setDifference a un campo inexistente da como resultado null .

Considere los siguientes documentos:

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

El primer documento no tiene una b campo, el segundo documento no tiene un a y el tercer documento no tiene ninguno.

Esto es lo que sucede cuando aplicamos $setDifference al a y b campos:

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

Resultado:

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

Tipo de datos incorrecto

Ambos operandos de $setDifference deben ser matrices. Si no lo son, se arroja un error.

Supongamos que nuestra colección contiene los siguientes documentos:

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

Y aplicamos $setDifference a esos documentos:

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

Resultado:

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

Valores duplicados

El $setDifference El operador filtra los duplicados en su resultado para generar una matriz que contiene solo entradas únicas. Además, no se especifica el orden de los elementos en la matriz de salida.

Supongamos que tenemos los siguientes documentos:

{ "_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" : [ ] }

Luego aplicamos el $setDifference operador para ellos:

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

Resultado:

{ "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 ] }