Mongodb 查找间隔为n的两个日期之间的行

Mongodb 查找间隔为n的两个日期之间的行,mongodb,date,mongodb-query,date-range,Mongodb,Date,Mongodb Query,Date Range,假设我一年中的每一天都有一个条目(或者可能是每小时、每分钟……)。我想做的是查询两个日期范围内的所有行,并且每间隔n只返回一个条目(例如,每周一个条目或每两天一个条目,…) 对于更具体的示例,“我的数据库”有如下条目: { _id: ..., date: ISODate("2014-07-T01:00:00Z"), values: ... } { _id: ..., date: ISODate("2014-07-02T12:00:00Z"), values: ... } ... { _id: .

假设我一年中的每一天都有一个条目(或者可能是每小时、每分钟……)。我想做的是查询两个日期范围内的所有行,并且每间隔n只返回一个条目(例如,每周一个条目或每两天一个条目,…)

对于更具体的示例,“我的数据库”有如下条目:

{ _id: ..., date: ISODate("2014-07-T01:00:00Z"), values: ... }
{ _id: ..., date: ISODate("2014-07-02T12:00:00Z"), values: ... }
...
{ _id: ..., date: ISODate("2015-03-17T12:00:00Z"), values: ... }
{ _id: ..., date: ISODate("2015-03-18T12:00:00Z"), values: ... }
{ _id: ..., date: ISODate("2014-12-05T12:00:00Z"), values: ... }
{ _id: ..., date: ISODate("2014-12-08T12:00:00Z"), values: ... }
{ _id: ..., date: ISODate("2014-12-11T12:00:00Z"), values: ... }
{ _id: ..., date: ISODate("2014-12-14T12:00:00Z"), values: ... }
...
我想要在
2014-12-05
2015-02-05
之间的所有结果,但每
3天只需要一个。结果集应如下所示:

{ _id: ..., date: ISODate("2014-07-T01:00:00Z"), values: ... }
{ _id: ..., date: ISODate("2014-07-02T12:00:00Z"), values: ... }
...
{ _id: ..., date: ISODate("2015-03-17T12:00:00Z"), values: ... }
{ _id: ..., date: ISODate("2015-03-18T12:00:00Z"), values: ... }
{ _id: ..., date: ISODate("2014-12-05T12:00:00Z"), values: ... }
{ _id: ..., date: ISODate("2014-12-08T12:00:00Z"), values: ... }
{ _id: ..., date: ISODate("2014-12-11T12:00:00Z"), values: ... }
{ _id: ..., date: ISODate("2014-12-14T12:00:00Z"), values: ... }
...

这可以通过某种方式实现吗?

使用聚合框架(以及非常复杂的查询),您可以实现您的目标。大致如下:

db.coll.aggregate([
    {$match: {
        date: {
            $gte: ISODate("2014-12-08T12:00:00.000Z"),
            $lt: ISODate("2014-12-12T00:00:00.000Z")
        }
    }},
    {$project:
        { date:1,
          value: 1,
          grp: { $let: 
                 {
                   vars: { delta:{$subtract:["$date", ISODate("2014-12-08T12:00:00.000Z")]}},
                   in: {$subtract:["$$delta", {$mod:["$$delta",3*24*3600*1000]}]}
                 }
               }
        }
    },
    {$sort: { date: 1 }},
    {$group: {_id:"$grp", date: {$first:"$date"}, value: {$first: "$value"}}}
])
  • $match
    步骤将仅保留所需范围内的行
  • 项目
    步骤将保留日期和值,并根据日期计算“组号”
    delta
    是给定日期与某个任意应用程序相关原点之间的时间差,单位为毫秒。由于MongoDB没有整数除法运算符,因此我使用了一个替换:
    delta mod(delta,3*24*3600*1000)
    。每3天(3天×24小时×3600秒×1000毫秒)改变一次
  • 根据您的用例,可能不需要执行
    $sort
    步骤。我使用它是为了在下一步保留每组的第一个日期和值时确保确定的结果
  • 最后(!)
    $group
    将根据之前计算的
    grp
    值对文档进行分组,只保留每组的第一个日期和值

您可以使用以下语法查询范围:

db.collection.find( { field: { $gt: value1, $lt: value2 } } );
在您的情况下,字段将是日期字段,此问题可能有助于设置值的格式:

编辑:我没有看到检索每个第n个文档的要求。在这种情况下,我不确定MongoDB是否内置了对这一点的支持。您可能需要自己操作返回的数组。在这种情况下,一旦获得范围,就可以按索引进行过滤。下面是一些示例(我无法找到Array.prototype.filter的有效使用方法,因为该函数不再需要索引,这与您想要的正好相反):

var结果=[]
对于(var i=0;i
这里的关键问题是3天分组。啊,是的,我错了。在我收集到这个问题的所有要求之前(在这个行业中要吸取的宝贵教训),我就超越了自己,开始回答。我会用可能的解决办法来修正我的问题谢谢!这工作得非常好:)我还考虑过抓取所有行,然后在程序中手动过滤它们。有些表每天只有一个条目,间隔时间仅为2-7天。你知道大数据集的查询性能会如何吗?@KeVin总是很难先验地谈论性能。但在这里,我想说的是,整个过程取决于
$match
步骤。在required字段上有一个索引,并且如果经过其他阶段的文档数量不太多,那么这应该表现得很好。也就是说,只有对实际数据集进行适当的基准测试,才能给出最终的答案。