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

Find rows between two dates that are an interval n apart

假设我有一年中每一天的条目(或者可能是每小时、每分钟……)。我想做的是查询两个日期范围内的所有行,并且每个间隔 return 一个条目 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: ... }

我想要 2014-12-052015-02-05 之间的所有结果,但每个 3 days 只需要一个结果。结果集应如下所示:

{ _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 步骤将只保留所需范围内的行;
  • project 步骤将保留日期和值,并将根据日期计算 "group number"。 delta 是给定日期与某些依赖于应用程序的任意来源之间的时间差(以毫秒为单位)。由于 MongoDB 没有 整数除法 运算符,因此我使用替代:delta-mod(delta, 3*24*3600*1000)。这将每 3 天更改一次(3 天 × 24 小时 × 3600 秒 × 1000 毫秒);
  • 根据您的用例,可能不需要 $sort 步骤。我使用它是为了在下一步保持每个组的 first 日期和值时确保确定性结果;
  • 最后 (!)$group 将根据之前计算的 grp 值对文档进行分组,仅保留每组的第一个日期和值。

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

db.collection.find( { field: { $gt: value1, $lt: value2 } } );

在您的情况下,字段将是日期字段,这个问题可能会帮助您设置值的格式:

return query based on date

编辑:我没有看到检索每个第 n 个文档的要求。在那种情况下,我不确定 MongoDB 是否内置了对此的支持。您可能必须自己操作返回的数组。在这种情况下,一旦获得范围,就可以按索引进行过滤。这是一些样板文件(我想不出 Array.prototype.filter 的有效使用,因为该函数消除了对索引的需要——与您想要的相反。):

var result =[]
for (var i = 0; i < inputArray.length ; i+=3) {     
    result.push(numList[i]);        
}
return result;