我有这样的文档结构:
{
"_id" : ObjectId("59d7cd63dc2c91e740afcdb"),
"dateJoined": ISODate("2014-12-28T16:37:17.984Z"),
"dateActivated": ISODate("2015-02-28T16:37:17.984Z"),
"enrolled" : [
{ "month":-10, "enrolled":'00'},
{ "month":-9, "enrolled":'00'},
{ "month":-8, "enrolled":'01'},
//other months
{ "month":8, "enrolled":'11'},
{ "month":9, "enrolled":'11'},
{ "month":10, "enrolled":'00'}
]
}
"一个月"注册中的值相对于dateJoined,范围从预先填充的-X到+ X.
我想计算一下注册价值为' 01'的文件数量。对于满足条件的每个子文档 - 例如"激活前5个月和激活后2个月#34;所有子文档项必须与条件匹配才能计为1. [是的,可以在激活之前注册:)]
由于月份值不是基于dateActivated,我应该能够为每个文档动态计算它。
我正在尝试使用MongoDB聚合框架,但不确定如何动态。
db.getCollection("enrollments").aggregate(
{ $match:{ //matching condition }},
{ $project: {
enrollments: {
$filter: {
input: "$enrolled",
as: "enrollment",
cond: {
$eq: ['$$enrolled.enroll', '01']
//how can I check for month value here?
}
}
}
}}
)
答案 0 :(得分:1)
这里的一般问题是要考虑"month"
值的范围,而不是"大于" -5
个月"之前"和"小于" +2
个月""记录在"enrolled"
数组条目中。
问题在于,由于这些值基于"dateJoined"
,因此需要根据"dateJoined"
和"dateActivated"
之间的正确间隔进行调整。这有效地表达了表达式:
monthsDiff = (yearActivated - yearJoined)*12 + (monthActivated - monthJoined)
where month >= ( startRange + monthsDiff ) and month <= ( endRange + monthsDiff )
and enrolled = "01"
或逻辑上表达&#34;表达范围之间的月份由加入和激活之间的月数差异调整&#34; 。
正如评论中所述,您需要首先将这些日期值存储为BSON Date
,而不是将其显示为&#34;字符串&#34;值。完成后,您可以应用以下聚合来计算与提供日期的差异,并在计算之前相应地从数组中过滤调整后的范围:
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
,您可以计算月份差异,也可以稍后应用于调整&#34;范围&#34;具有$gte
和$lte
的逻辑条件中的值。
最后,因为$filter
只发出一个只包含与条件匹配的条目的数组,以便计算&#34;计数&#34;我们应用$size
返回&#34;过滤&#34;的长度。数组,这是&#34; count&#34;比赛。
答案 1 :(得分:1)
如果您存储的是天数而不是几个月,则可以尝试以下聚合。
天差异以计算dateActivated
和dateJoined
之间的天数,以抵消相对于dateActivated
的入场天数。
将daysdiff
与以下值进行比较。
enrollment
在dateActivated
enrollment
在dateActivated
$or
上述条件&amp;值$and
的{{1}}。
enrolled