Den allmänna frågan här är att inkludera intervallet för "month"
värden i beaktande där det är "större än" -5
månader "före" och "mindre än" +2
månader "efter" som registrerats i "enrolled"
arrayposter.
Problemet är att eftersom dessa värden är baserade på "dateJoined"
, måste de justeras med rätt intervall mellan "dateJoined"
och "dateActivated"
. Detta gör uttrycket effektivt:
monthsDiff = (yearActivated - yearJoined)*12 + (monthActivated - monthJoined)
where month >= ( startRange + monthsDiff ) and month <= ( endRange + monthsDiff )
and enrolled = "01"
Eller logiskt uttryckt "Månader mellan det uttryckta intervallet justerat med antalet månaders skillnad mellan att gå med och aktivera" .
Som nämnts i kommentaren är det allra första du behöver här att lagra dessa datumvärden som ett BSON Date
i motsats till deras nuvarande skenbara "strängvärden". När det är gjort kan du sedan använda följande aggregering för att beräkna skillnaden från de angivna datumen och filtrera det justerade intervallet i enlighet därmed från matrisen innan du räknar:
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" ] }
]
}
}
}
}
}
}
}}
])
Så detta gäller samma $filter
till den array som du försökte, men tar nu även hänsyn till de justerade värdena för månadsintervallet att filtrera efter.
För att göra detta lättare att läsa använder vi $let
som tillåter beräkning av det gemensamma värdet som erhålls för $$monthsDiff
som implementerat i en variabel. Här används uttrycket som ursprungligen förklarades, med $year
och $month
för att extrahera dessa numeriska värden från de lagrade datumen.
Använda de ytterligare matematiska operatorerna $add
, $subtract
och $multiply
du kan beräkna både skillnaden i månader och även senare tillämpa för att justera "intervall"-värdena i de logiska förhållandena med $gte
och $lte
.
Slutligen, eftersom $filter
skickar ut en rad endast poster som matchar villkoren, för att "räkna" tillämpar vi $size
som returnerar längden på den "filtrerade" arrayen, vilket är "antal" av matchningar.
Beroende på ditt avsedda syfte kan hela uttrycket också tillhandahållas i argument till $sum
som en $group
ackumulator, om det då verkligen var avsikten.