Yêu cầu chung ở đây là bao gồm phạm vi cho "month"
các giá trị được xem xét trong đó nó "lớn hơn" -5
tháng "trước" và "nhỏ hơn" +2
tháng "sau" như được ghi trong "enrolled"
các mục nhập mảng.
Vấn đề là vì các giá trị này dựa trên "dateJoined"
, chúng cần được điều chỉnh theo khoảng thời gian chính xác giữa "dateJoined"
và "dateActivated"
. Điều này làm cho biểu thức hiệu quả:
monthsDiff = (yearActivated - yearJoined)*12 + (monthActivated - monthJoined)
where month >= ( startRange + monthsDiff ) and month <= ( endRange + monthsDiff )
and enrolled = "01"
Hoặc được diễn đạt một cách logic "Các tháng giữa phạm vi được thể hiện được điều chỉnh bằng số tháng chênh lệch giữa việc tham gia và kích hoạt" .
Như đã nêu trong nhận xét, điều đầu tiên bạn cần làm ở đây là lưu trữ các giá trị ngày đó dưới dạng BSON Date
trái ngược với các giá trị "chuỗi" rõ ràng hiện tại của chúng. Sau khi hoàn tất, bạn có thể áp dụng phép tổng hợp sau để tính toán sự khác biệt so với các ngày đã cung cấp và lọc phạm vi đã điều chỉnh cho phù hợp từ mảng trước khi tính:
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" ] }
]
}
}
}
}
}
}
}}
])
Vì vậy, điều này áp dụng cùng một $filter
vào mảng mà bạn đang cố gắng, nhưng bây giờ cũng tính đến các giá trị đã điều chỉnh trong phạm vi tháng để lọc.
Để giúp bạn đọc dễ dàng hơn, chúng tôi áp dụng $let
cho phép tính toán giá trị chung thu được cho $$monthsDiff
như được triển khai trong một biến. Đây là nơi áp dụng biểu thức được giải thích ban đầu, sử dụng $year
và $month
để trích xuất các giá trị số đó từ các ngày được lưu trữ.
Sử dụng các toán tử toán học bổ sung $add
, $subtract
và $multiply
bạn có thể tính toán cả chênh lệch theo tháng và sau đó cũng có thể áp dụng để điều chỉnh các giá trị "phạm vi" trong điều kiện logic với $gte
và $lte
.
Cuối cùng, vì $filter
tạo ra một mảng chỉ gồm các mục nhập phù hợp với các điều kiện, để "đếm", chúng tôi áp dụng $size
trả về độ dài của mảng "đã lọc", là "số lượng" kết quả phù hợp.
Tùy thuộc vào mục đích dự định của bạn, toàn bộ biểu thức cũng có thể được cung cấp trong đối số cho $sum
với tư cách là $group
tích lũy, nếu sau đó thực sự là ý định.