mongodb - Mongodb 统计过去 X 周的文档 - 不是过去 XX 天
问题描述
虽然这里有类似的问题,如何查找/计算特定周范围内的文件,但我无法找到,如何匹配/计算最近 X 周的文件。考虑这个查询:
db.getCollection('post').aggregate([
{
$match: {
createdDate: {'$gte': new Date(new Date() - 7 * 60 * 60 * 24 * 1000)},
}
},
{
$group: {
_id: {$week: '$createdDate'},
count: {$sum: 1}
}
}
])
此查询计算过去 7 天的文档数,并按周数对计数进行分组 - 但结果实际上包含两个文件:本周的文档数和上周从当前日期开始的文档数天 - 7 天。
示例 - 从星期三开始的查询:
- 上周最后 7 天:[周四、周五、周六、周日] | 当前周:[周一、周二、周三]
- last week上一周:[周一、周二、周三、周四、周五、周六、周日] | 当前周:[ ]
无论是在一周的第一天还是一周的最后一天开始,查询都应该返回正确的结果。还必须考虑年份变化 - 12 月的最后一周有第 52 周,1 月的第一周有第 1 周。
在没有任何相关文件的情况下数周可能会导致其他潜在问题。您只是不能按周数对过去 21 天的文档进行分组并使用$sort
and $limit
,因为没有任何相关文档的周不会出现在分组中。
解决方案
花一些时间试图找到一个基于$week
运营商的自己的解决方案并决定将其发布在这里,但最后我意识到, harrgit kohli建议的方法更好。我稍后会解释。经过进一步调查,我注意到第一个答案存在一些重大缺陷,原因是在没有考虑任何相关文件的情况下没有花费数周时间。
更新:
我终于找到了一个基于周数的解决方案,即使查询在一年中发生变化,它也应该给出正确的结果。关键是减去52(每年的周数)
db.getCollection('post').aggregate([
{
{
$match: { // match posts at least 2 Weeks + 6 days old
createdDate: {'$gte':new Date(new Date().setDate(new Date().getDate() - 3 * 7 - 1))},
}
},
{
$addFields: {
createdInWeek: {
$cond: {
if: {
$eq: [
{ $year: "$createdDate"},
{ $year: new Date()}
]
}, then: {
$week: "$createdDate"
}, else: {
$subtract: [ { $week: "$createdDate"}, 52]
}
}
},
currentWeek: { $week: new Date() },
}
},
{
$match: {
$expr: {
$and: [
{$lte: ["$createdInWeek", { $subtract: ["$currentWeek", 1] } ]},
{$gte: ["$createdInWeek", { $subtract: ["$currentWeek", 2] } ]},
]
}
}
},
{
$group: {
_id: {$week: '$createdDate'},
count: {
$sum: 1
}
}
},
])
因此,包含 53 周的年份可能仍然存在问题,请参考此处
以前的:
db.getCollection('post').aggregate([
{ // optional, can pre-sort your collection, so you don't add fields to every document in a huge collection
$match: {
createdDate: {'$gte':new Date(new Date().setDate(new Date().getDate() - 2 * 7 + 1))},
}
},
{
$addFields: {
createdInWeek: { $week: '$createdDate' },
currentWeek: { $week: new Date() },
}
},
{
$match: { // use of $expr. necessary since MongoDb 3.6 see https://stackoverflow.com/a/58567621/1991697
$expr: {
$and: [
{$lte: ["$createdInWeek", { $subtract: ["$currentWeek", 1] } ]},
{$gte: ["$createdInWeek", { $subtract: ["$currentWeek", 2] } ]},
]
}
}
},
{
$group: {
_id: {$week: '$createdDate'},
count: {
$sum: 1
}
}
},
])
这种方法让 Mongo 计算当前周的周数以及createdDate
集合中每个文档的周数,然后您可以使用进一步的$match
运算符进行简单的文件筛选。它还可以让您更轻松地设置周范围。
但
如果您的周范围将在一年的休息时间分开,这可能会失败。(一月的第一周是第 0 周,十二月的最后一周是第 52 周)
推荐阅读
- node.js - 需要 JWT expiresIn 字段显示在控制台上
- javascript - 隐藏一个 div 并显示另一个
- c# - 如何重载“==”运算符来确定两个 ID 号是否相同?
- android - getApplicationBanner 返回 null
- html - 在移动设备下显示翻牌的全部内容
- python-3.x - 如何获取?使用python在数据帧之间进行降序排序
- search - 在 Bootstrap 4 的小屏幕上,搜索图标未正确附加搜索表单
- swift - Firebase 离线支持:在用户离线时上传帖子,当用户在 iOS Swift 应用程序中在线时同步
- ajax - 如何将'id'值放入ajax url?
- java - 使用java读取pdf中的表格