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

Korzystanie z wartości dynamicznej w agregacji

Ogólne pytanie to uwzględnienie zakresu dla "month" rozważane wartości, gdzie jest „większy niż” -5 miesięcy „przed” i „mniej niż” +2 miesiące „po” zarejestrowane w "enrolled" wpisy tablicy.

Problem polega na tym, że ponieważ te wartości są oparte na "dateJoined" , należy je dostosować do właściwego odstępu między "dateJoined" i "dateActivated" . To sprawia, że ​​wyrażenie jest efektywne:

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

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

Lub logicznie wyrażone „Miesiące między wyrażonym zakresem skorygowane o liczbę miesięcy różnicy między dołączeniem a aktywacją” .

Jak wspomniano w komentarzu, pierwszą rzeczą, którą musisz tutaj, jest przechowywanie tych wartości dat jako BSON Date w przeciwieństwie do ich obecnych pozornych wartości „stringowych”. Gdy to zrobisz, możesz zastosować następującą agregację, aby obliczyć różnicę od podanych dat i odpowiednio odfiltrować dostosowany zakres z tablicy przed zliczeniem:

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

Dotyczy to więc tego samego $filter do tablicy, którą próbowałeś, ale teraz uwzględnia również skorygowane wartości w zakresie miesięcy, według których ma być filtrowane.

Aby ułatwić czytanie, stosujemy $let co pozwala na obliczenie wspólnej wartości uzyskanej dla $$monthsDiff jak zaimplementowano w zmiennej. Tutaj stosuje się pierwotnie wyjaśnione wyrażenie, używając $year i $month aby wyodrębnić te wartości liczbowe z zapisanych dat.

Korzystanie z dodatkowych operatorów matematycznych $add , $subtract i $multiply możesz obliczyć różnicę w miesiącach, a później zastosować do dostosowania wartości „zakresu” w warunkach logicznych za pomocą $gte i $lte .

Wreszcie, ponieważ $filter emituje tablicę tylko wpisów spełniających warunki, aby "zliczyć" stosujemy $size która zwraca długość "filtrowanej" tablicy, która jest "liczbą" dopasowań.

W zależności od zamierzonego celu całe wyrażenie można również podać w argumencie $sum jako $group akumulator, jeśli to rzeczywiście było zamiarem.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Co jest nie tak z MongoDB usuwającym zapytanie za pomocą mongodb java dla podtablicy dokumentu?

  2. Przechowuj obrazy w bazie danych MongoDB

  3. Wiele zapytań $where w MongoDB

  4. Skrypt MongoDB do tworzenia kopii zapasowej replikacji ustawionej lokalnie na Windows Server

  5. Problemy z połączeniem MongoDB na platformie Azure