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.