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

Aggregato Mongodb, come contare i documenti in base a criteri di intervallo?

Quello che vuoi è il $cond operatore e alcune condizioni nidificate con $and . Ma questo dovrebbe darti esattamente quello che vuoi.

db.collection.aggregate([
    {"$group": {
      "_id": {"$cond": [
          {"$gte": ["$LoadTime", 2000] },
          "Slowest",                                   // return "Slowest" where true
          {"$cond": [
              {"$and": [
                  {"$lt": ["$LoadTime", 2000] },
                  {"$gte": ["$LoadTime", 1000] }
              ]},
              "Slow",                                  // then "Slow" here where true
              {"$cond": [
                  {"$and": [
                      {"$lt": ["$LoadTime", 1000] },
                      {"$gte": ["$LoadTime", 500 ] }
                  ]},
                  "Medium",                            // then "Medium" where true
                  "Fast"                               // and finally "Fast" < 500
              ]}
          ]}
      ]},
      "count": {"$sum": 1}
    }},
    {"$sort": { "count": 1 }}
])

Poiché il tuo tempo è intero millisecondi puoi capire perché ho chiesto la modifica.

Così come $cond è un ternario operatore, sono necessari tre argomenti:

  • Una condizione per valutare che restituisce un booleano
  • Un valore di ritorno in cui la condizione è vera
  • Un valore restituito in cui la condizione è falsa

Pertanto l'idea è che tu nidi tutte le condizioni, passando al successivo prova su falso finché non hai trovato una condizione da soddisfare e un valore da restituire.

Il $e parte è una serie di condizioni includere. Questo ti dà gli gamme . Quindi nelle parti più lunghe:

          {"$cond": [                             // Evaluate here
              {"$and": [                          // Within the range of the next 2
                  {"$lt": ["$LoadTime", 2000] },
                  {"$gte": ["$LoadTime", 1000] }
              ]},
              "Slow",                            // true condition - return
              {"$cond": [                        // false - move to next eval

A cascata attraverso di te rimani con "Veloce" per times meno di 500 millisecondi.

Ognuna di queste keys viene emesso nel gruppo e noi semplicemente { $sum: 1 } per ottenere un conteggio man mano che vengono raggruppati.

Se ne hai bisogno nell'implementazione della tua lingua, l'intera pipeline contenuto all'interno di

è solo JSON, quindi puoi analizzarlo nella tua struttura dati nativa se la traduzione manuale ti sfugge o se come me sei solo pigro.

MODIFICA

A causa dei commenti sembra necessario spiegare il modulo della domanda presentata. Quindi qui l'addendum di modifica per chiarimenti.

Quando impara uso della pipeline di aggregazione e, in effetti, di buona pratica per la scrittura e il test una serie complessa di fasi o logica, trovo utile visualizzare i risultati implementando parti un passo alla volta . Quindi, nel caso di scrivere una cosa del genere, il mio primo il passo sarebbe il seguente:

db.collection.aggregate([
    {"$group": {
      "_id": {"$cond": [
          {"$gte": ["$LoadTime", 2000] },
          "Slowest",
          null
       ]}
    }}
])

Ora questo mi darebbe il conteggio di "Più lento" come mi aspetterei e poi bucket tutto il resto in null . Quindi c'è una fase in cui vedo i risultati finora. Ma quando test In realtà farei qualcosa del genere prima di passare a costruire una catena:

db.collection.aggregate([
    {"$group": {
      "_id": {"$cond": [
          {"$and": [
              {"$lt": ["$LoadTime", 2000] },
              {"$gte": ["$LoadTime", 1000] }
          ]},
          "Slow",
          null
      ]}
    }}
])

Quindi sto solo ottenendo i risultati per "Slow" (tra 2000 e 1000) con tutto il resto in null benna. Quindi il mio conteggio generale rimane lo stesso.

Nella finale query, come è stato sottolineato, in un ternario condizione nidificata come questa, la prima lo stadio è già valutato false per gli articoli testati dal successivo operatore. Ciò significa che non maggiore di il valore che è stato già testato nel primo fase, e ciò ovvia alla necessità di testare quella condizione in modo che questo potrebbe essere scritto come segue:

db.collection.aggregate([
    {"$group": {
      "_id": {"$cond": [
          {"$gte": ["$LoadTime", 2000] },       // Caught everything over 2000
          "Slowest",
          {"$cond": [
              {"$gte": ["$LoadTime", 1000] }    // Catch things still over 1000
              "Slow",
              {"$cond": [                       // Things under 1000 go here

              // and so on

E che cortocircuito la valutazione in quanto non esiste un reale bisogno di testare le cose che non arriveranno alla successiva condizione logica.

Quindi puramente per motivi visivi e per pura pigrizia di taglia e incolla logica, finiamo con il modulo espanso utilizzando $e condizione per avvolgere la gamma. Ma per chi non è abituato l'utilizzo del ternario forma c'è un segnale visivo chiaro che i risultati abbinati in questa fase cadranno tra i valori di 2000ms e 1000ms , e così via, che è ciò che desideri come risultato in ogni intervallo.

Come ho detto, non è necessario avere a causa di come funziona la logica, ma era una fase di sviluppo, ed è chiaro alle persone che devono ancora pensare utilizzo del ternario forma che $cond fornisce.