En MongoDB, el $indexOfArray
El operador de canalización de agregación busca en una matriz una aparición de un valor especificado y devuelve el índice de matriz de la primera aparición.
Sintaxis
La sintaxis es así:
{ $indexOfArray: [ <array expression>, <search expression>, <start>, <end> ] }
donde:
<array expression>
es la matriz a buscar.<search expression>
es el valor que desea encontrar en la matriz.<start>
es un argumento opcional que especifica un punto de partida para buscar en la matriz. Puede ser cualquier expresión válida que se resuelva en un número entero no negativo.<end>
es un argumento opcional que especifica una posición de índice final para la búsqueda. Puede ser cualquier expresión válida que se resuelva en un número entero no negativo.
En MongoDB, las matrices se basan en cero, por lo que el recuento del índice comienza en cero (0
).
Si no se encuentra el valor especificado, $indexOfArray
devuelve -1
.
Si hay varias instancias del valor especificado, solo se devuelve la primera.
Ejemplo
Supongamos que tenemos una colección llamada products
con los siguientes documentos:
{ "_id" : 1, "prod" : "Bat", "sizes" : [ "XS", "M", "L" ] } { "_id" : 2, "prod" : "Hat", "sizes" : [ "XS", "S", "L", "XL" ] } { "_id" : 3, "prod" : "Cap", "sizes" : [ "XXS", "XS", "M", "XL" ] } { "_id" : 4, "prod" : "Zap", "sizes" : [ 10, 12, 15 ] } { "_id" : 5, "prod" : "Tap", "sizes" : [ 15, 16, 20 ] }
Aquí hay un ejemplo de cómo aplicar $indexOfArray
a esos documentos:
db.products.aggregate(
[
{ $match: { _id: { $in: [ 1, 2, 3, 4, 5 ] } } },
{
$project:
{
_id: 0,
sizes: 1,
result: { $indexOfArray: [ "$sizes", "XS" ] }
}
}
]
)
Resultado:
{ "sizes" : [ "XS", "M", "L" ], "result" : 0 } { "sizes" : [ "XS", "S", "L", "XL" ], "result" : 0 } { "sizes" : [ "XXS", "XS", "M", "XL" ], "result" : 1 } { "sizes" : [ 10, 12, 15 ], "result" : -1 } { "sizes" : [ 15, 16, 20 ], "result" : -1 }
En los primeros dos documentos, el valor de búsqueda se encontró en la posición 0
(las matrices están basadas en cero).
En el tercer documento, se encontró en la posición 1
. Observe que la búsqueda fue para una coincidencia exacta. No devolvió la posición 0
, aunque el valor en la posición 0
contiene el valor de búsqueda (es decir, XXS
contiene XS
).
El valor de búsqueda no se encontró en los dos últimos documentos, por lo que -1
fue devuelto.
Aquí hay otro ejemplo, excepto que esta vez buscamos un valor numérico:
db.products.aggregate(
[
{ $match: { _id: { $in: [ 1, 2, 3, 4, 5 ] } } },
{
$project:
{
_id: 0,
sizes: 1,
result: { $indexOfArray: [ "$sizes", 15 ] }
}
}
]
)
Resultado:
{ "sizes" : [ "XS", "M", "L" ], "result" : -1 } { "sizes" : [ "XS", "S", "L", "XL" ], "result" : -1 } { "sizes" : [ "XXS", "XS", "M", "XL" ], "result" : -1 } { "sizes" : [ 10, 12, 15 ], "result" : 2 } { "sizes" : [ 15, 16, 20 ], "result" : 0 }
Especifique una posición inicial
Puede proporcionar un tercer argumento para especificar una posición de índice inicial para la búsqueda.
Ejemplo:
db.products.aggregate(
[
{ $match: { _id: { $in: [ 4, 5 ] } } },
{
$project:
{
_id: 0,
sizes: 1,
result: { $indexOfArray: [ "$sizes", 15, 1 ] }
}
}
]
)
Resultado:
{ "sizes" : [ 10, 12, 15 ], "result" : 2 } { "sizes" : [ 15, 16, 20 ], "result" : -1 }
En este caso, la expresión de búsqueda no se encontró en el segundo documento (documento 5). Esto se debe a que comenzamos la búsqueda en la posición 1
, y aunque ese documento contiene la expresión de búsqueda, está en la posición 0
(antes de la posición inicial de la búsqueda).
Especifique una posición final
También puede proporcionar un cuarto argumento para especificar la posición final del índice para la búsqueda.
Si proporciona este argumento, también debe proporcionar una posición inicial. Si no lo hace, este argumento se interpretará como el punto de partida.
Ejemplo:
db.products.aggregate(
[
{ $match: { _id: { $in: [ 1, 2, 3 ] } } },
{
$project:
{
_id: 0,
sizes: 1,
result: { $indexOfArray: [ "$sizes", "XS", 0, 1 ] }
}
}
]
)
Resultado:
{ "sizes" : [ "XS", "M", "L" ], "result" : 0 } { "sizes" : [ "XS", "S", "L", "XL" ], "result" : 0 } { "sizes" : [ "XXS", "XS", "M", "XL" ], "result" : -1 }
El tercer documento devolvió -1
lo que significa que no se encontró la expresión de búsqueda.
Esto es lo que sucede si incrementamos la posición final del índice en 1:
db.products.aggregate(
[
{ $match: { _id: { $in: [ 1, 2, 3 ] } } },
{
$project:
{
_id: 0,
sizes: 1,
result: { $indexOfArray: [ "$sizes", "XS", 0, 2 ] }
}
}
]
)
Resultado:
{ "sizes" : [ "XS", "M", "L" ], "result" : 0 } { "sizes" : [ "XS", "S", "L", "XL" ], "result" : 0 } { "sizes" : [ "XXS", "XS", "M", "XL" ], "result" : 1 }
Esta vez se incluyó el valor y se devolvió su posición de índice.
Arreglos vacíos
Buscar una matriz vacía devuelve -1
.
db.products.aggregate(
[
{ $match: { _id: { $in: [ 6 ] } } },
{
$project:
{
_id: 0,
sizes: 1,
result: { $indexOfArray: [ "$sizes", "XS" ] }
}
}
]
)
Resultado:
{ "sizes" : [ ], "result" : -1 }
Campos faltantes
Si el campo no está en el documento, $indexOfArray
devuelve null
.
Supongamos que tenemos el siguiente documento:
{ "_id" : 8, "prod" : "Map" }
Esto es lo que sucede cuando aplicamos $indexOfArray
:
db.products.aggregate(
[
{ $match: { _id: { $in: [ 8 ] } } },
{
$project:
{
_id: 0,
sizes: 1,
result: { $indexOfArray: [ "$sizes", "XS" ] }
}
}
]
)
Resultado:
{ "result" : null }
Valores nulos
Si la expresión de la matriz es null
(en lugar de una matriz), $indexOfArray
devuelve null
.
Supongamos que tenemos el siguiente documento:
{ "_id" : 7, "prod" : "Lap", "sizes" : null }
Esto es lo que sucede cuando aplicamos $indexOfArray
:
db.products.aggregate(
[
{ $match: { _id: { $in: [ 7 ] } } },
{
$project:
{
_id: 0,
sizes: 1,
result: { $indexOfArray: [ "$sizes", "XS" ] }
}
}
]
)
Resultado:
{ "sizes" : null, "result" : null }
Sin embargo, cuando la expresión de búsqueda es null
, el resultado es -1
, a menos que la expresión de matriz también sea null
o falta su campo:
db.products.aggregate(
[
{ $match: { _id: { $in: [ 1, 2, 3, 4, 5, 6, 7, 8 ] } } },
{
$project:
{
_id: 0,
sizes: 1,
result: { $indexOfArray: [ "$sizes", null ] }
}
}
]
)
Resultado:
{ "sizes" : [ "XS", "M", "L" ], "result" : -1 } { "sizes" : [ "XS", "S", "L", "XL" ], "result" : -1 } { "sizes" : [ "XXS", "XS", "M", "XL" ], "result" : -1 } { "sizes" : [ 10, 12, 15 ], "result" : -1 } { "sizes" : [ 15, 16, 20 ], "result" : -1 } { "sizes" : [ ], "result" : -1 } { "sizes" : null, "result" : null } { "result" : null }
Tipo de datos incorrecto
Si la expresión de la matriz es del tipo de datos incorrecto, $indexOfArray
devuelve un error.
Supongamos que tenemos el siguiente documento:
{ "_id" : 9, "prod" : "Box", "sizes" : "XXL" }
Esto es lo que sucede cuando aplicamos $indexOfArray
a ese documento:
db.products.aggregate(
[
{ $match: { _id: { $in: [ 9 ] } } },
{
$project:
{
_id: 0,
sizes: 1,
result: { $indexOfArray: [ "$sizes", "XXL" ] }
}
}
]
)
Resultado:
uncaught exception: Error: command failed: { "ok" : 0, "errmsg" : "$indexOfArray requires an array as a first argument, found: string", "code" : 40090, "codeName" : "Location40090" } : 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
Como indica el mensaje de error, $indexOfArray requires an array as a first argument
.