Общата молба тук е да включите диапазона за "month"
разглеждани стойности, когато е „по-голямо от“ -5
месеца „преди“ и „по-малко от“ +2
месеца „след“, както е записано в "enrolled"
записи в масив.
Проблемът е, че тъй като тези стойности са базирани на "dateJoined"
, те трябва да бъдат коригирани с правилния интервал между "dateJoined"
и "dateActivated"
. Това прави израза ефективен:
monthsDiff = (yearActivated - yearJoined)*12 + (monthActivated - monthJoined)
where month >= ( startRange + monthsDiff ) and month <= ( endRange + monthsDiff )
and enrolled = "01"
Или логично изразено „Месеците между изразения диапазон, коригирани с броя на месеците разлика между присъединяването и активирането“ .
Както е посочено в коментара, първото нещо, което трябва да направите тук, е да съхраните тези стойности на датата като BSON Date
за разлика от техните настоящи очевидни "низови" стойности. След като направите това, можете да приложите следното обобщаване, за да изчислите разликата от предоставените дати и да филтрирате съответно коригирания диапазон от масива, преди да преброите:
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" ] }
]
}
}
}
}
}
}
}}
])
Така че това важи за същия $filter
към масива, който се опитвахте, но сега взема предвид и коригираните стойности в диапазона от месеци, по които да филтрирате.
За да направим това по-лесно за четене, прилагаме $let
което позволява изчисляване на общата стойност, получена за $$monthsDiff
както е имплементирано в променлива. Тук се прилага изразът, обяснен първоначално, като се използва $year
и $month
за да извлечете тези числови стойности от съхранените дати.
Използване на допълнителните математически оператори $add
, $subtract
и $multiply
можете да изчислите както разликата в месеци, така и по-късно да приложите, за да коригирате стойностите на "диапазон" в логическите условия с $gte
и $lte
.
И накрая, защото $filter
излъчва масив само от записи, отговарящи на условията, за да „преброим“, прилагаме $size
който връща дължината на "филтрирания" масив, който е "броят" на съвпаденията.
В зависимост от вашата предвидена цел, целият израз може също да бъде предоставен в аргумент на $sum
като $group
акумулатор, ако това наистина е било намерението.