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

Използване на динамична стойност при агрегиране

Общата молба тук е да включите диапазона за "month" разглеждани стойности, когато е „по-голямо от“ -5 месеца „преди“ и „по-малко от“ +2 месеца „след“, както е записано в "enrolled" записи в масив.

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

monthsDiff = (yearActivated - yearJoined)*12 + (monthActivated - monthJoined)

where month >= ( startRange + monthsDiff ) and month <= ( endRange + monthsDiff )
and enrolled = "01"

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

Както е посочено в коментара, първото нещо, което трябва да направите тук, е да съхраните тези стойности на датата като BSON Date за разлика от техните настоящи очевидни "низови" стойности. След като направите това, можете да приложите следното обобщаване, за да изчислите разликата от предоставените дати и да филтрирате съответно коригирания диапазон от масива, преди да преброите:

var rangeStart = -5,
    rangeEnd = 2;

db.getCollection('enrollments').aggregate([
  { "$project": {
    "enrollments": {
      "$size": {
        "$filter": {
          "input": "$enrolled",
          "as": "e",
          "cond": {
            "$let": {
              "vars": {
                "monthsDiff": {
                  "$add": [
                    { "$multiply": [
                      { "$subtract": [
                        { "$year": "$dateActivated" },
                        { "$year": "$dateJoined" }
                      ]},
                      12
                    }},
                    { "$subtract": [
                      { "$month": "$dateActivated" },
                      { "$month": "$dateJoined" }
                    ]}
                  ]
                }
              },
              "in": {
                "$and": [
                  { "$gte": [ { "$add": [ rangeStart, "$$monthsDiff" ] }, "$$e.month" ] },
                  { "$lte": [ { "$add": [ rangeEnd, "$$monthsDiff" ] }, "$$e.month" ] },
                  { "$eq": [ "$$e.enrolled", "01" ] }
                ]
              }
            }
          } 
        }
      }
    }
  }}
])

Така че това важи за същия $filter към масива, който се опитвахте, но сега взема предвид и коригираните стойности в диапазона от месеци, по които да филтрирате.

За да направим това по-лесно за четене, прилагаме $let което позволява изчисляване на общата стойност, получена за $$monthsDiff както е имплементирано в променлива. Тук се прилага изразът, обяснен първоначално, като се използва $year и $month за да извлечете тези числови стойности от съхранените дати.

Използване на допълнителните математически оператори $add , $subtract и $multiply можете да изчислите както разликата в месеци, така и по-късно да приложите, за да коригирате стойностите на "диапазон" в логическите условия с $gte и $lte .

И накрая, защото $filter излъчва масив само от записи, отговарящи на условията, за да „преброим“, прилагаме $size който връща дължината на "филтрирания" масив, който е "броят" на съвпаденията.

В зависимост от вашата предвидена цел, целият израз може също да бъде предоставен в аргумент на $sum като $group акумулатор, ако това наистина е било намерението.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Тестване за интеграция на Spring Boot с вграден MongoDB

  2. Как да поддържам MongoDB - данни на работещ Docker контейнер в ново изображение?

  3. Java MongoDB запазва множество документи наведнъж

  4. MongoDB 4.0 JRException:Опцията 'cursor' е задължителна, с изключение на aggregate с аргумента обяснение

  5. Запазете подмножество от колекция MongoDB в друга колекция