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
.