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

MongoDB $rango

En MongoDB, el $range El operador de canalización de agregación devuelve una secuencia generada de números en una matriz.

Esta secuencia de números se basa en los valores de entrada que proporcione.

Sintaxis

La sintaxis es así:

{ $range: [ <start>, <end>, <non-zero step> ] }

Donde <start> es el inicio y <end> es el final de la secuencia. Cada uno de estos puede ser cualquier expresión válida que se resuelva en un número entero.

<non-zero step> es un argumento opcional cuyo valor predeterminado es 1. Este argumento le permite especificar un valor de incremento. Si se proporciona, debe ser una expresión válida que se resuelva en un número entero distinto de cero.

Ejemplo

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

{ "_id" : 1, "start" : 0, "end" : 5 }
{ "_id" : 2, "start" : 1, "end" : 5 }

Podemos usar el $range operador para devolver una matriz basada en los valores de esos documentos.

db.range.aggregate(
   [
     { $match: { _id: { $in: [ 1, 2 ] } } },
     {
       $project:
          {
            _id: 0,
            start: 1,
            end: 1,
            result: { $range: [ "$start", "$end" ] }
          }
     }
   ]
)

Resultado:

{ "start" : 0, "end" : 5, "result" : [ 0, 1, 2, 3, 4 ] }
{ "start" : 1, "end" : 5, "result" : [ 1, 2, 3, 4 ] }

En este caso, no proporcionamos un tercer argumento, por lo que $range usa su valor de paso predeterminado de 1. Por lo tanto, los elementos de la matriz se incrementan en 1.

Añadir un incremento explícito

Podemos agregar un tercer argumento para especificar explícitamente cuánto debe incrementarse cada elemento de la matriz.

Supongamos que nuestra colección contiene los siguientes documentos:

{ "_id" : 3, "start" : 0, "end" : 5, "step" : 1 }
{ "_id" : 4, "start" : 0, "end" : 10, "step" : 2 }
{ "_id" : 5, "start" : 1, "end" : 10, "step" : 2 }
{ "_id" : 6, "start" : 100, "end" : 150, "step" : 10 }

Estos documentos tienen un step campo, por lo que podemos usar ese campo para el valor incremental para el documento respectivo.

Ahora apliquemos $range a esos documentos e incluir el step campo como tercer argumento:

db.range.aggregate(
   [
     { $match: { _id: { $in: [ 3, 4, 5, 6 ] } } },
     {
       $project:
          {
            _id: 0,
            start: 1,
            end: 1,
            step: 1,
            result: { $range: [ "$start", "$end", "$step" ] }
          }
     }
   ]
)

Resultado:

{ "start" : 0, "end" : 5, "step" : 1, "result" : [ 0, 1, 2, 3, 4 ] }
{ "start" : 0, "end" : 10, "step" : 2, "result" : [ 0, 2, 4, 6, 8 ] }
{ "start" : 1, "end" : 10, "step" : 2, "result" : [ 1, 3, 5, 7, 9 ] }
{ "start" : 100, "end" : 150, "step" : 10, "result" : [ 100, 110, 120, 130, 140 ] }

Valores de paso negativos

El paso puede ser un valor negativo, aunque esto debe hacerse en el contexto de la disminución desde un start más alto número a un end más bajo número.

Agreguemos algunos documentos más a nuestra colección:

{ "_id" : 7, "start" : 0, "end" : 5, "step" : -1 }
{ "_id" : 8, "start" : 5, "end" : 0, "step" : -1 }
{ "_id" : 9, "start" : 0, "end" : -5, "step" : -1 }

Ahora apliquemos $range a esos documentos:

db.range.aggregate(
   [
     { $match: { _id: { $in: [ 7, 8, 9 ] } } },
     {
       $project:
          {
            _id: 0,
            start: 1,
            end: 1,
            step: 1,
            result: { $range: [ "$start", "$end", "$step" ] }
          }
     }
   ]
)

Resultado:

{ "start" : 0, "end" : 5, "step" : -1, "result" : [ ] }
{ "start" : 5, "end" : 0, "step" : -1, "result" : [ 5, 4, 3, 2, 1 ] }
{ "start" : 0, "end" : -5, "step" : -1, "result" : [ 0, -1, -2, -3, -4 ] }

Podemos ver que el primer documento devolvió una matriz vacía porque el valor del paso negativo está fuera del rango proporcionado por start y end campos.

Sin embargo, los documentos posteriores produjeron un rango decreciente de valores.

Cuando el paso es cero

El valor del paso debe ser un número entero distinto de cero. Proporcionar un paso de 0 devuelve un error.

Supongamos que agregamos el siguiente documento a nuestra colección:

{ "_id" : 10, "start" : 1, "end" : 5, "step" : 0 }

Esto es lo que sucede cuando aplicamos $range a ese documento:

db.range.aggregate(
   [
     { $match: { _id: { $in: [ 10 ] } } },
     {
       $project:
          {
            _id: 0,
            start: 1,
            end: 1,
            result: { $range: [ "$start", "$end", "$step" ] }
          }
     }
   ]
)

Resultado:

uncaught exception: Error: command failed: {
	"ok" : 0,
	"errmsg" : "$range requires a non-zero step value",
	"code" : 34449,
	"codeName" : "Location34449"
} : 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

El mensaje de error nos dice explícitamente que $range requires a non-zero step value .

Pasos nulos

El paso no puede ser null tampoco.

Supongamos que tenemos el siguiente documento:

{ "_id" : 11, "start" : 1, "end" : 5, "step" : null }

Y aplicamos $range a ello:

db.range.aggregate(
   [
     { $match: { _id: { $in: [ 11 ] } } },
     {
       $project:
          {
            _id: 0,
            start: 1,
            end: 1,
            result: { $range: [ "$start", "$end", "$step" ] }
          }
     }
   ]
)

Resultado:

uncaught exception: Error: command failed: {
	"ok" : 0,
	"errmsg" : "$range requires a numeric step value, found value of type:null",
	"code" : 34447,
	"codeName" : "Location34447"
} : 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

Esto nos dice que $range requires a numeric step value, found value of type:null .

Rangos nulos

Si el start y/o end los campos son null , luego se devuelve un error.

Supongamos que tenemos el siguiente documento:

{ "_id" : 11, "start" : 1, "end" : 5, "step" : null }

Y aplica $range a ello:

db.range.aggregate(
   [
     { $match: { _id: { $in: [ 11 ] } } },
     {
       $project:
          {
            _id: 0,
            start: 1,
            end: 1,
            result: { $range: [ "$start", "$end", "$step" ] }
          }
     }
   ]
)

Resultado:

uncaught exception: Error: command failed: {
	"ok" : 0,
	"errmsg" : "$range requires a numeric starting value, found value of type: null",
	"code" : 34443,
	"codeName" : "Location34443"
} : 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

Esto nos dice que $range requires a numeric starting value, found value of type: null .

Aparecería un mensaje similar si el valor final fuera nulo.

Aquí hay un documento con un null valor final:

{ "_id" : 13, "start" : 1, "end" : null, "step" : 1 }

Apliquemos $range :

db.range.aggregate(
   [
     { $match: { _id: { $in: [ 13 ] } } },
     {
       $project:
          {
            _id: 0,
            start: 1,
            end: 1,
            result: { $range: [ "$start", "$end", "$step" ] }
          }
     }
   ]
)

Resultado:

uncaught exception: Error: command failed: {
	"ok" : 0,
	"errmsg" : "$range requires a numeric ending value, found value of type: null",
	"code" : 34445,
	"codeName" : "Location34445"
} : 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

Esta vez nos dice que $range requires a numeric ending value, found value of type: null .