MongoDB
 sql >> Baza danych >  >> NoSQL >> MongoDB

Agregat Mongodb, Jak liczyć dokumenty według kryteriów interwałowych?

To, czego potrzebujesz, to $cond operator i sporo warunków zagnieżdżonych z $and . Ale to powinno dać ci dokładnie to, czego chcesz.

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

Ponieważ Twój czas jest cały milisekundy możesz zobaczyć, dlaczego poprosiłem o edycję.

Tak jak $cond jest trójargumentem operatora, potrzebne są trzy argumenty:

  • Warunek do oceny, który zwraca wartość logiczną
  • Wartość zwracana, gdy warunek jest prawda
  • Wartość zwracana, gdy warunek jest fałsz

Dlatego chodzi o to, aby zagnieździć warunki przez cały czas, przechodząc do następnego test na fałsz dopóki nie znajdziesz warunku do dopasowania i wartości do zwrócenia.

$i część to tablica warunków zawrzeć. Daje to zakresy . Więc w najdłuższych częściach:

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

Kaskadowo przez ciebie pozostaje "Szybko" na times poniżej 500 milisekund.

Każdy z tych keys jest emitowany do grupy i po prostu { $sum: 1 } aby uzyskać liczbę, ponieważ są one zgrupowane.

Jeśli potrzebujesz tego we własnej implementacji języka, cały pipeline zawartość w

to po prostu JSON, więc możesz przetworzyć go do swojej natywnej struktury danych, jeśli nie masz możliwości tłumaczenia ręcznego lub jeśli tak jak ja jesteś po prostu leniwy.

EDYTUJ

Ze względu na komentarze wydaje się konieczne wyjaśnienie formularza prezentowanego zapytania. Oto dodatek do edycji w celu wyjaśnienia.

Kiedy nauka wykorzystanie potoku agregacji i rzeczywiście dobra praktyka do pisania i testowania złożonej serii etapów lub logiki, uważam, że warto wizualizować wyniki poprzez implementację części jeden krok na raz . Więc w przypadku pisania czegoś takiego mój pierwszy krok byłby następujący:

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

Teraz dałoby mi to liczbę „najwolniej”, zgodnie z oczekiwaniami, a następnie zasobnik wszystko inne w null . Jest więc etap, na którym widzę dotychczasowe wyniki. Ale podczas testowania Właściwie zrobiłbym coś takiego, zanim przejdę do budowania łańcucha:

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

Otrzymuję więc tylko wyniki dla słowa „Powoli” (pomiędzy 2000 i 1000) ze wszystkim innym w null wiaderko. Więc moja ogólna liczba pozostaje taka sama.

W finale zapytanie, jak wskazano, w trójargumentowym warunek zagnieżdżony, taki jak ten, pierwszy etap ma już oceniane false dla przedmiotów testowanych przez następne operator. Oznacza to, że nie większe niż wartość, która była już testowana w pierwszym etapie, co eliminuje potrzebę testowania tego stanu, więc może być napisane w następujący sposób:

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

I że zwarcia ocena, ponieważ nie ma prawdziwego musisz przetestować pod kątem rzeczy, które nie przejdą do następnego warunku logicznego.

Więc czysto z powodów wizualnych i za zwykłe lenistwo wytnij i wklej logiki, kończymy z rozwiniętym formularzem za pomocą $i warunek zawinięcia Zakres. Ale dla tych nieprzyzwyczajonych użycie trójnego ponieważ istnieje wyraźna wskazówka wizualna że wyniki dopasowywane w tej fazie będą znajdować się między wartości 2000ms i 1000ms , i tak dalej, czego oczekujesz jako wynik w każdym zakresie.

Jak powiedziałem, niepotrzebne ze względu na działanie logiki, ale było faza rozwoju i jest jasne do ludzi, którzy jeszcze nie zajęli się nimi użycie trójnego formować $cond zapewnia.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Kolejność Mongo według długości tablicy

  2. mongodb $where zapytanie do pobrania treści poddokumentu

  3. pymongo nie może połączyć się z bazą danych na zdalnym serwerze

  4. Jak poprawnie przeszukiwać zagnieżdżony dokument MongoDB za pomocą Pythona?

  5. Używanie SqlBulkCopy z MongoDB