En MongoDB, el $setIntersection
El operador de canalización de agregación acepta dos o más matrices y devuelve una matriz que contiene los elementos que aparecen en todas las matrices de entrada.
$setIntersection
acepta dos o más argumentos, todos los cuales pueden ser cualquier expresión válida siempre que cada uno se resuelva en una matriz. $setIntersection
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 $setIntersection
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: { $setIntersection: [ "$a", "$b" ] }
}
}
]
)
Resultado:
{ "a" : [ 1, 2, 3 ], "b" : [ 1, 2, 3 ], "result" : [ 1, 2, 3 ] } { "a" : [ 1, 2, 3 ], "b" : [ 1, 2 ], "result" : [ 1, 2 ] } { "a" : [ 1, 2 ], "b" : [ 1, 2, 3 ], "result" : [ 1, 2 ] } { "a" : [ 1, 2, 3 ], "b" : [ 3, 4, 5 ], "result" : [ 3 ] } { "a" : [ 1, 2, 3 ], "b" : [ 4, 5, 6 ], "result" : [ ] }
Matrices anidadas
El $setIntersection
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 $setIntersection
a esos dos documentos:
db.data.aggregate(
[
{ $match: { _id: { $in: [ 6, 7 ] } } },
{
$project:
{
_id: 0,
a: 1,
b: 1,
result: { $setIntersection: [ "$a", "$b" ] }
}
}
]
)
Resultado:
{ "a" : [ 1, 2, 3 ], "b" : [ [ 1, 2, 3 ] ], "result" : [ ] } { "a" : [ 1, 2, 3 ], "b" : [ [ 1, 2 ], 3 ], "result" : [ 3 ] }
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 contener cualquiera de los valores que estaban en la matriz en a
.
Sin embargo, 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 ] }
El documento 8 contiene una matriz anidada tanto en el a
y b
campos, y ambas matrices son idénticas.
Esto es lo que sucede cuando aplicamos $setIntersection
a esos documentos:
db.data.aggregate(
[
{ $match: { _id: { $in: [ 8, 9 ] } } },
{
$project:
{
_id: 0,
a: 1,
b: 1,
result: { $setIntersection: [ "$a", "$b" ] }
}
}
]
)
Resultado:
{ "a" : [ [ 1, 2, 3 ] ], "b" : [ [ 1, 2, 3 ] ], "result" : [ [ 1, 2, 3 ] ] } { "a" : [ [ 1, 2, 3 ] ], "b" : [ [ 1, 2 ], 3 ], "result" : [ ] }
En el primer documento, a
coincide con b
exactamente, por lo que el resultado es una matriz idéntica (una matriz externa que contiene la matriz interna).
En el segundo documento, el contenido de a
no coincide con ninguno de los contenidos de b
, por lo que se devuelve una matriz vacía.
Campos faltantes
Aplicando $setIntersection
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 $setIntersection
al a
y b
campos:
db.data.aggregate(
[
{ $match: { _id: { $in: [ 10, 11, 12 ] } } },
{
$project:
{
_id: 0,
a: 1,
b: 1,
result: { $setIntersection: [ "$a", "$b" ] }
}
}
]
)
Resultado:
{ "a" : [ 1, 2, 3 ], "result" : null } { "b" : [ 1, 2, 3 ], "result" : null } { "result" : null }
Tipo de datos incorrecto
Todos los operandos de $setIntersection
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 $setIntersection
a esos documentos:
db.data.aggregate(
[
{ $match: { _id: { $in: [ 13, 14, 15 ] } } },
{
$project:
{
_id: 0,
a: 1,
b: 1,
result: { $setIntersection: [ "$a", "$b" ] }
}
}
]
)
Resultado:
Error: command failed: { "ok" : 0, "errmsg" : "All operands of $setIntersection must be arrays. One argument is of type: double", "code" : 17047, "codeName" : "Location17047" } : 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 $setIntersection
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 $setIntersection
operador para ellos:
db.data.aggregate(
[
{ $match: { _id: { $in: [ 16, 17, 18, 19, 20, 21 ] } } },
{
$project:
{
_id: 0,
a: 1,
b: 1,
result: { $setIntersection: [ "$a", "$b" ] }
}
}
]
)
Resultado:
{ "a" : [ 1, 1, 2, 2, 3, 3 ], "b" : [ 1, 2, 3 ], "result" : [ 1, 2, 3 ] } { "a" : [ 1, 1, 2, 2, 3, 3 ], "b" : [ 1, 2 ], "result" : [ 1, 2 ] } { "a" : [ 1, 1, 2, 2, 3, 3 ], "b" : [ ], "result" : [ ] } { "a" : [ 3, 2, 1, 2, 3, 1 ], "b" : [ 2, 3, 1 ], "result" : [ 1, 2, 3 ] } { "a" : [ 1, 3, 2, 2, 3, 1 ], "b" : [ 2, 1 ], "result" : [ 1, 2 ] } { "a" : [ 2, 3, 1, 2, 3, 1 ], "b" : [ ], "result" : [ ] }
Más de dos argumentos
Como se mencionó, $setIntersection
acepta dos o más argumentos. Todos los ejemplos anteriores utilizaron dos argumentos. Aquí hay uno que usa tres argumentos.
Supongamos que tenemos los siguientes documentos:
{ "_id" : 22, "a" : [ 1, 2 ], "b" : [ 1, 2 ], "c" : [ 1, 2 ] } { "_id" : 23, "a" : [ 1, 2 ], "b" : [ 1, 2 ], "c" : [ 1, 2, 3 ] }
Estos documentos tienen un campo adicional:una c
campo.
Ahora apliquemos $setIntersection
a esos tres campos:
db.data.aggregate(
[
{ $match: { _id: { $in: [ 22, 23 ] } } },
{
$project:
{
_id: 0,
a: 1,
b: 1,
c: 1,
result: { $setIntersection: [ "$a", "$b", "$c" ] }
}
}
]
)
Resultado:
{ "a" : [ 1, 2 ], "b" : [ 1, 2 ], "c" : [ 1, 2 ], "result" : [ 1, 2 ] } { "a" : [ 1, 2 ], "b" : [ 1, 2 ], "c" : [ 1, 2, 3 ], "result" : [ 1, 2 ] }