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

Mongodb aggregat, Hvordan tæller man dokumenter efter intervalkriterier?

Det, du ønsker, er $cond operator og en hel del indlejrede forhold med $and . Men dette burde give dig præcis, hvad du ønsker.

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

Da din tid er hel millisekunder kan du se, hvorfor jeg bad om redigeringen.

Altså som $cond er en ternær operatør, kræver det tre argumenter:

  • En betingelse for at evaluere, som returnerer en boolean
  • En returværdi, hvor betingelsen er sand
  • En returværdi, hvor betingelsen er falsk

Derfor er tanken, at du rede betingelserne hele vejen igennem, flytter til næste test på falsk indtil du har fundet en betingelse at matche, og en værdi at returnere.

$and del er en række betingelser at medtage. Dette giver dig intervallerne . Så i de længste dele:

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

Cascading gennem dig står tilbage med "Hurtig" i times under 500 millisekunder.

Hver af disse keys udsendes til gruppen, og vi { $sum: 1 } for at få en optælling, når de er grupperet sammen.

Hvis du har brug for det i din egen sprogimplementering, hele pipeline indhold i

er bare JSON, så du kan parse det ind i din oprindelige datastruktur, hvis håndoversættelse undgår dig, eller hvis du ligesom mig bare er doven.

REDIGER

På grund af kommentarerne det synes nødvendigt at forklare formen af den præsenterede forespørgsel. Så her er redigeringstillægget til afklaring.

Når du lærer brug af aggregeringspipelinen, og faktisk god praksis til udskrivning og test en kompleks række af faser eller logik, finder jeg det nyttigt at visualisere resultaterne ved at implementere dele et trin ad gangen . Så i tilfælde af at skrive sådan noget min første trin ville være som følger:

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

Det ville nu give mig antallet af "Langsommest", som jeg ville forvente, og derefter spand alt andet til null . Så der er et stadie, hvor jeg ser resultaterne indtil videre. Men når du tester Jeg ville faktisk gøre sådan noget, før jeg gik videre med at bygge en kæde op:

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

Så jeg får bare resultaterne for "Langsom" (mellem 2000 og 1000) med alt andet i null spand. Så mit samlede antal forbliver det samme.

I finalen forespørgsel, som det blev påpeget, i en ternær tilstand, der er indlejret som denne, den første scenen har allerede evalueret false for de emner, der testes af den næste operatør. Det betyder, at de ikke er det større end den værdi, som allerede blev testet i den første fase, og det fjerner behovet for at teste for den tilstand, så dette kunne skrives som følger:

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

Og det kortslutter evalueringen, da der ikke er nogen rigtig nødt til at teste for ting, der ikke kommer igennem til den næste logiske tilstand.

rent af visuelle årsager og for ren og skær dovenskab ved klip og indsæt logik, ender vi med den udvidede form ved at bruge $and betingelse for at ombryde rækkevidden. Men for dem ikke vant til brugen af ​​ternary form er der en klar visuel cue at de resultater, der matches i denne fase, vil falde mellem værdierne 2000ms og 1000ms ,og så videre, hvilket er, hvad du vil have som resultat i hvert område.

Som sagt unødvendigt at have på grund af hvordan logikken fungerer, men det var en udviklingsfase, og er overskuelig til de mennesker, der endnu ikke har forstået deres hoveder brug af ternary form den $cond giver.




  1. Ved hjælp af MongoDB, hvordan opdaterer jeg et underdokument til et underarray, når elementets position er ukendt?

  2. Hvordan kører jeg en forklaringsforespørgsel med 2.4 C# Mongo-driveren?

  3. Sådan skriver du et python-program, der understøtter flere databaser

  4. Ydeevnesammenligning af brug af Redis-hashes vs mange nøgler