MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

MongoDB $ intervallo

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 .