sql >> Databáze >  >> NoSQL >> MongoDB

Agregát Mongodb, Jak počítat dokumenty podle intervalových kritérií?

Co chcete, je $cond operátor a několik vnořených podmínek s $and . Ale to by vám mělo dát přesně to, co chcete.

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 }}
])

Protože váš čas je celý milisekund můžete vidět, proč jsem požádal o úpravu.

Tedy jako $cond je ternární operátor, vyžaduje tři argumenty:

  • Podmínka k vyhodnocení, která vrací logickou hodnotu
  • Vrácená hodnota, kde je podmínka pravda
  • Vrácená hodnota, kde je podmínka false

Myšlenka je tedy taková, že hnízdíte podmínky v celém textu, přechod na další test na false dokud nenajdete podmínku, která se má shodovat, a hodnotu, kterou chcete vrátit.

$and součástí je pole podmínek zahrnout. Tím získáte rozsahy . Takže v nejdelších částech:

          {"$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

Kaskádové procházení vás times ponechá na "Rychlý". pod 500 milisekund.

Každý z těchto keys je odeslán do skupiny a my jen { $sum: 1 } abyste získali počet, když jsou seskupeny.

Pokud to potřebujete ve své vlastní jazykové implementaci, celý pipeline obsah v rámci

je pouze JSON, takže jej můžete analyzovat do své nativní datové struktury, pokud vám ruční překlad uniká, nebo pokud jste jako já jen líní.

UPRAVIT

Kvůli komentářům zdá se nutné vysvětlit formulář předloženého dotazu. Zde tedy pro upřesnění dodatek k úpravám.

Při učení použití agregačního kanálu a skutečně dobrý postup pro zápis a testování složitou řadu fází nebo logiky, považuji za užitečné vizualizovat výsledky implementací částí po jednotlivých krocích . Takže v případě psaní takové věci moje první krok by byl následující:

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

To by mi teď dalo počet „Nejpomalejší“, jak bych očekával, a pak kbelík vše ostatní do null . Je tu tedy fáze, kdy zatím vidím výsledky. Ale při testování Vlastně bych udělal něco takového, než se pustím do budování řetězce:

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

Takže právě dostávám výsledky pro "Slow" (mezi 2000 a 1000) se vším ostatním v null Kbelík. Takže můj celkový počet zůstává stejný.

Ve finále dotaz, jak bylo zdůrazněno, v ternární podmínka, která je vnořena jako tato, první etapa již vyhodnoceno false pro položky testované dalším operátor. To znamená, že nejsou větší než hodnota, která již byla testována v první fázi, a to eliminuje potřebu testovat tento stav, aby to mohlo být zapsán následovně:

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

A to zkraty hodnocení, protože žádné skutečné neexistuje potřebují otestovat věci, které neprojdou do další logické podmínky.

Tedy čistě z vizuálních důvodů a pro čistou lenost vyjmout a vložit logiky, skončíme s rozšířenou formou pomocí $and stav zabalit rozsah. Ale pro ty nejsou zvyklí použití ternary existuje jasná vizuální vodítka že výsledky porovnávané v této fázi spadají mezi hodnoty 2000ms a 1000ms , a tak dále, což je to, co chcete jako výsledek v každém rozsahu.

Jak jsem řekl, zbytečné to mít kvůli tomu, jak funguje logika, ale bylo fázi vývoje a je jasný lidem, kteří se teprve rozejdou použití ternary formulář, který $cond poskytuje.




  1. Jak indexování zlepšuje výkon dotazů v mongodb

  2. Mongoid není v dotazu

  3. Object.keys, jak získat seznam klíčů v mongodb

  4. Jaký je nejlepší postup pro připojení/odpojení k databázi?