MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Faixa $ do MongoDB


No MongoDB, o $range operador de pipeline de agregação retorna uma sequência gerada de números em uma matriz.

Essa sequência de números é baseada nos valores de entrada que você fornece.

Sintaxe


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

Onde <start> é o início e <end> é o fim da sequência. Cada um deles pode ser qualquer expressão válida que resolva para um inteiro.

<non-zero step> é um argumento opcional cujo padrão é 1. Esse argumento permite especificar um valor de incremento. Se fornecido, deve ser uma expressão válida que resolva para um número inteiro diferente de zero.

Exemplo


Suponha que tenhamos uma coleção chamada range com os seguintes documentos:
{ "_id" : 1, "start" : 0, "end" : 5 }
{ "_id" : 2, "start" : 1, "end" : 5 }

Podemos usar o $range operador para retornar uma matriz com base nos valores desses 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 ] }

Nesse caso, não fornecemos um terceiro argumento e, portanto, $range usa seu valor de passo padrão de 1. Portanto, os elementos da matriz são incrementados em 1.

Adicionar um incremento explícito


Podemos adicionar um terceiro argumento para especificar explicitamente quanto cada elemento do array deve ser incrementado.

Suponha que nossa coleção contenha os seguintes 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 }

Esses documentos têm um step campo, e assim podemos usar esse campo para o valor de incremento para o respectivo documento.

Agora vamos aplicar $range a esses documentos e inclua a step campo como um terceiro 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 etapa negativos


O passo pode ser um valor negativo, embora isso precise ser feito no contexto de decrementar de um start mais alto número para um end inferior número.

Vamos adicionar mais alguns documentos à nossa coleção:
{ "_id" : 7, "start" : 0, "end" : 5, "step" : -1 }
{ "_id" : 8, "start" : 5, "end" : 0, "step" : -1 }
{ "_id" : 9, "start" : 0, "end" : -5, "step" : -1 }

Agora vamos aplicar $range a esses 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 o primeiro documento retornou um array vazio porque o valor do passo negativo está fora do intervalo fornecido pelo start e end Campos.

No entanto, os documentos subsequentes produziram uma faixa decrescente de valores.

Quando o passo é zero


O valor da etapa deve ser um número inteiro diferente de zero. Fornecendo uma etapa de 0 retorna um erro.

Suponha que adicionamos o seguinte documento à nossa coleção:
{ "_id" : 10, "start" : 1, "end" : 5, "step" : 0 }

Veja o que acontece quando aplicamos $range a esse 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

A mensagem de erro nos diz explicitamente que $range requires a non-zero step value .

Etapas nulas


A etapa não pode ser null ou.

Suponha que temos o seguinte documento:
{ "_id" : 11, "start" : 1, "end" : 5, "step" : null }

E aplicamos $range para ele:
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

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

Intervalos nulos


Se o start e/ou end os campos são null , um erro será retornado.

Suponha que temos o seguinte documento:
{ "_id" : 11, "start" : 1, "end" : 5, "step" : null }

E aplique $range para ele:
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

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

Uma mensagem semelhante apareceria se o valor final fosse nulo.

Aqui está um documento com um null valor final:
{ "_id" : 13, "start" : 1, "end" : null, "step" : 1 }

Vamos aplicar $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

Desta vez, ele nos diz que $range requires a numeric ending value, found value of type: null .