MongoDB
 sql >> база данни >  >> NoSQL >> MongoDB

Агрегат Mongodb, Как да броим документи по интервални критерии?

Това, което искате, е $cond оператор и доста вложени условия с $and . Но това трябва да ви даде точно това, което искате.

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

Тъй като времето ви е цяло милисекунди можете да видите защо поисках редакцията.

Така като $cond е троичен оператор, той приема три аргумента, които са:

  • Условие за оценка, което връща булева стойност
  • Върната стойност, където условието е true
  • Върната стойност, при която условието е false

Следователно идеята е да гнездите условията навсякъде, преминавайки към следващия тест наfalse докато не намерите условие за съвпадение и стойност за връщане.

$ и част е масив от условия да включва. Това ви дава диапазоните . Така че в най-дългите части:

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

Каскадното преминаване през вас остава с „Бързо“ за times под 500 милисекунди.

Всеки от тези keys се излъчва към групата и ние просто { $sum: 1 } за да получите брой, тъй като са групирани заедно.

Ако имате нужда от това във вашата собствена езикова реализация, целият pipeline съдържание в

е само JSON, така че можете да анализирате това в собствената си структура от данни, ако преводът на ръка ви убягва или ако като мен просто сте мързеливи.

РЕДАКТИРАНЕ

Поради коментарите изглежда необходимо да се обясниформата на представената заявка. Ето добавката за редактиране за пояснение.

При сучаване използване на тръбопровода за агрегиране и наистина добра практика за изписване и тестване сложна поредица от етапи или логика, смятам, че е полезно да визуализирате резултатите чрез прилагане на части стъпка по стъпка . Така че в случай на писане на такова нещо моятпърво стъпката ще бъде както следва:

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

Сега това ще ми даде броя на „Най-бавно“, както бих очаквал, и след това кофа всичко останало в null . Така че има етап, в който виждам резултатите досега. Но при тестване Всъщност бих направил нещо подобно, преди да премина към изграждането на верига:

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

Така че просто получавам резултатите за „Бавно“ (между 2000 и 1000) с всичко останало в null кофа. Така че общият ми брой остава същият.

Във вина финала заявка, както беше посочено, в троичен условие, което е вложено като това, първо етап има вече оценено false за артикулите, които се тестват от следа оператор. Това означава, че не са по-голямо от стойността, която вече беше тествана в първи етап и това премахва необходимостта от тестване за това състояние, така че това може се запише по следния начин:

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

И това късо съединение оценката като няма реалната трябва да тествате за неща, които няма да стигнат до следващото логическо условие.

Така чечисто поради визуални причини и за чистия мързел на изрязване и поставяне логика, завършваме с разширената форма, използвайки $and условие за обвиване диапазона. Но за тези, които не са свикнали използването на троичен форма има ясен визуален знак че резултатите, съпоставени в тази фаза, ще попаднат между стойностите на 2000ms и 1000ms и т.н., което искате като резултат във всеки диапазон.

Както казах, не е необходимо да имаш поради начина, по който работи логиката, но беше фаза на развитие и е ясен на хората, които тепърва ще разумяват използване на троичен форма, която $cond предоставя.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Кога да затворите връзката с базата данни MongoDB в Nodejs

  2. Персонализирана система за съхранение за GridFS (MongoDB)?

  3. Нормално ли е да има много връзки между node и mongo при използване на mongoose?

  4. MongoDB намира къде ключът е равен на низ от масив

  5. Възможно ли е да се получат полетата в реда на проекция в Aggregation Frameworks mongo