In MongoDB, il $range
l'operatore della pipeline di aggregazione restituisce una sequenza generata di numeri in una matrice.
Questa sequenza di numeri si basa sui valori di input forniti.
Sintassi
La sintassi è questa:
{ $range: [ <start>, <end>, <non-zero step> ] }
Dove <start>
è l'inizio e <end>
è la fine della sequenza. Ognuna di queste può essere qualsiasi espressione valida che si risolve in un numero intero.
<non-zero step>
è un argomento facoltativo il cui valore predefinito è 1. Questo argomento consente di specificare un valore di incremento. Se fornita, deve essere un'espressione valida che si risolve in un numero intero diverso da zero.
Esempio
Supponiamo di avere una collezione chiamata range
con i seguenti documenti:
{ "_id" : 1, "start" : 0, "end" : 5 } { "_id" : 2, "start" : 1, "end" : 5 }
Possiamo usare il $range
operatore per restituire un array basato sui valori in quei documenti.
db.range.aggregate(
[
{ $match: { _id: { $in: [ 1, 2 ] } } },
{
$project:
{
_id: 0,
start: 1,
end: 1,
result: { $range: [ "$start", "$end" ] }
}
}
]
)
Risultato:
{ "start" : 0, "end" : 5, "result" : [ 0, 1, 2, 3, 4 ] } { "start" : 1, "end" : 5, "result" : [ 1, 2, 3, 4 ] }
In questo caso, non abbiamo fornito un terzo argomento, quindi $range
utilizza il valore di passaggio predefinito di 1. Pertanto, gli elementi dell'array vengono incrementati di 1.
Aggiungi un incremento esplicito
Possiamo aggiungere un terzo argomento per specificare in modo esplicito di quanto dovrebbe aumentare ogni elemento dell'array.
Supponiamo che la nostra collezione contenga i seguenti documenti:
{ "_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 }
Questi documenti hanno un step
campo, e così possiamo usare quel campo per il valore incrementale per il rispettivo documento.
Ora applichiamo $range
a quei documenti e includi il step
campo come terzo argomento:
db.range.aggregate(
[
{ $match: { _id: { $in: [ 3, 4, 5, 6 ] } } },
{
$project:
{
_id: 0,
start: 1,
end: 1,
step: 1,
result: { $range: [ "$start", "$end", "$step" ] }
}
}
]
)
Risultato:
{ "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 ] }
Valori dei passi negativi
Il passaggio può essere un valore negativo, anche se questo deve essere fatto nel contesto del decremento da un start
più alto numero a un end
inferiore numero.
Aggiungiamo qualche altro documento alla nostra collezione:
{ "_id" : 7, "start" : 0, "end" : 5, "step" : -1 } { "_id" : 8, "start" : 5, "end" : 0, "step" : -1 } { "_id" : 9, "start" : 0, "end" : -5, "step" : -1 }
Ora applichiamo $range
a quei documenti:
db.range.aggregate(
[
{ $match: { _id: { $in: [ 7, 8, 9 ] } } },
{
$project:
{
_id: 0,
start: 1,
end: 1,
step: 1,
result: { $range: [ "$start", "$end", "$step" ] }
}
}
]
)
Risultato:
{ "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 ] }
Possiamo vedere che il primo documento ha restituito un array vuoto perché il valore del passaggio negativo è al di fuori dell'intervallo fornito da start
e end
campi.
Tuttavia, i documenti successivi hanno prodotto un intervallo di valori decrescente.
Quando il passo è zero
Il valore del passaggio deve essere un numero intero diverso da zero. Fornire un passaggio di 0
restituisce un errore.
Supponiamo di aggiungere il seguente documento alla nostra raccolta:
{ "_id" : 10, "start" : 1, "end" : 5, "step" : 0 }
Ecco cosa succede quando applichiamo $range
a quel documento:
db.range.aggregate(
[
{ $match: { _id: { $in: [ 10 ] } } },
{
$project:
{
_id: 0,
start: 1,
end: 1,
result: { $range: [ "$start", "$end", "$step" ] }
}
}
]
)
Risultato:
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
Il messaggio di errore ci dice esplicitamente che $range requires a non-zero step value
.
Passi nulli
Il passaggio non può essere null
neanche.
Supponiamo di avere il seguente documento:
{ "_id" : 11, "start" : 1, "end" : 5, "step" : null }
E applichiamo $range
ad esso:
db.range.aggregate(
[
{ $match: { _id: { $in: [ 11 ] } } },
{
$project:
{
_id: 0,
start: 1,
end: 1,
result: { $range: [ "$start", "$end", "$step" ] }
}
}
]
)
Risultato:
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
Questo ci dice che $range requires a numeric step value, found value of type:null
.
Intervalli nulli
Se il start
e/o end
i campi sono null
, viene restituito un errore.
Supponiamo di avere il seguente documento:
{ "_id" : 11, "start" : 1, "end" : 5, "step" : null }
E applica $range
ad esso:
db.range.aggregate(
[
{ $match: { _id: { $in: [ 11 ] } } },
{
$project:
{
_id: 0,
start: 1,
end: 1,
result: { $range: [ "$start", "$end", "$step" ] }
}
}
]
)
Risultato:
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
Questo ci dice che $range requires a numeric starting value, found value of type: null
.
Un messaggio simile verrebbe visualizzato se il valore finale fosse nullo.
Ecco un documento con un null
valore finale:
{ "_id" : 13, "start" : 1, "end" : null, "step" : 1 }
Applichiamo $range
:
db.range.aggregate(
[
{ $match: { _id: { $in: [ 13 ] } } },
{
$project:
{
_id: 0,
start: 1,
end: 1,
result: { $range: [ "$start", "$end", "$step" ] }
}
}
]
)
Risultato:
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
Questa volta ci dice che $range requires a numeric ending value, found value of type: null
.