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

Utilizzo di un valore dinamico nell'aggregazione

La richiesta generale qui è di includere l'intervallo per il "month" valori in considerazione dove è "maggiore di" il -5 mesi "prima" e "meno di" il +2 mesi "dopo" come registrato all'interno del "enrolled" voci dell'array.

Il problema è che poiché questi valori sono basati su "dateJoined" , devono essere regolati in base all'intervallo corretto tra il "dateJoined" e il "dateActivated" . Questo rende l'espressione efficace:

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

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

Oppure espresso in modo logico "I mesi tra l'intervallo espresso rettificato dalla differenza di mesi tra l'adesione e l'attivazione" .

Come affermato nel commento, la prima cosa che devi fare qui è memorizzare quei valori di data come BSON Date in contrasto con i loro attuali valori di "stringa". Fatto ciò, puoi quindi applicare la seguente aggregazione per calcolare la differenza rispetto alle date fornite e filtrare l'intervallo corretto di conseguenza dall'array prima del conteggio:

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

Quindi questo vale lo stesso $filter all'array che stavi tentando, ma ora tiene conto anche dei valori modificati nell'intervallo di mesi in base al quale filtrare.

Per facilitare la lettura, applichiamo $let che permette di calcolare il valore comune ottenuto per $$monthsDiff come implementato in una variabile. Qui è dove viene applicata l'espressione spiegata originariamente, utilizzando $year e $month per estrarre quei valori numerici dalle date memorizzate.

Utilizzo degli operatori matematici aggiuntivi $add , $subtract e $multiply puoi calcolare sia la differenza in mesi che anche successivamente applicare per regolare i valori "range" nelle condizioni logiche con $gte e $lte .

Infine, perché $filter emette un array di sole voci che soddisfano le condizioni, per "contare" applichiamo $size che restituisce la lunghezza dell'array "filtrato", che è il "conteggio" delle corrispondenze.

A seconda dello scopo previsto, l'intera espressione può anche essere fornita come argomento a $sum come $group accumulatore, se allora era davvero l'intenzione.