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