La demande générale ici est d'inclure la plage pour le "month"
valeurs en considération où il est "supérieur" au -5
mois "avant" et "moins que" le +2
mois "après" tel qu'enregistré dans le "enrolled"
entrées de tableau.
Le problème est que puisque ces valeurs sont basées sur "dateJoined"
, ils doivent être ajustés par l'intervalle correct entre le "dateJoined"
et le "dateActivated"
. Cela rend l'expression efficace :
monthsDiff = (yearActivated - yearJoined)*12 + (monthActivated - monthJoined)
where month >= ( startRange + monthsDiff ) and month <= ( endRange + monthsDiff )
and enrolled = "01"
Ou exprimé logiquement "Les mois entre la plage exprimée ajustés par le nombre de mois de différence entre l'adhésion et l'activation" .
Comme indiqué dans le commentaire, la toute première chose que vous devez faire ici est de stocker ces valeurs de date en tant que BSON Date
par opposition à leurs valeurs "chaînes" apparentes actuelles. Une fois cela fait, vous pouvez ensuite appliquer l'agrégation suivante pour calculer la différence par rapport aux dates fournies et filtrer la plage ajustée en conséquence à partir du tableau avant de compter :
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" ] }
]
}
}
}
}
}
}
}}
])
Cela s'applique donc au même $filter
au tableau que vous essayiez, mais prend désormais en compte les valeurs ajustées sur la plage de mois à filtrer également.
Pour faciliter la lecture, nous appliquons $let
qui permet de calculer la valeur commune obtenue pour $$monthsDiff
comme implémenté dans une variable. Voici où l'expression expliquée à l'origine est appliquée, en utilisant $year
et $month
pour extraire ces valeurs numériques des dates telles qu'elles sont stockées.
Utilisation des opérateurs mathématiques supplémentaires $add
, $subtract
et $multiply
vous pouvez calculer à la fois la différence en mois et également appliquer ultérieurement pour ajuster les valeurs de "plage" dans les conditions logiques avec $gte
et $lte
.
Enfin, parce que $filter
émet un tableau des seules entrées correspondant aux conditions, afin de "compter" nous appliquons $size
qui renvoie la longueur du tableau "filtré", qui est le "nombre" de correspondances.
En fonction de votre objectif, l'expression entière peut également être fournie en argument de $sum
en tant que $group
accumulateur, si c'était bien l'intention.