说我今年每天都有一个条目(或者可能是每小时,每分钟......)。我想要做的是查询两个日期范围之间的所有行,并且每个区间 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: ... }
...
这可以以某种方式完成吗?
答案 0 :(得分:3)
使用聚合框架(以及非常复杂的查询),您可以实现目标。以下内容:
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
步骤将保留日期和值,并将根据日期计算“组号”。 delta
是给定日期与某些任意应用程序相关原点之间的时差(以毫秒为单位)。由于MongoDB没有整数除法运算符,我使用替换:delta-mod(delta, 3*24*3600*1000)
。这将每3天更改一次(3天×24小时×3600秒×1000毫秒); $sort
步骤。我使用它是为了确保在下一步中保持每个组的第一个日期和值时的确定性结果; $group
将按之前计算的grp
值对文档进行分组,仅保留每个组的第一个日期和值。答案 1 :(得分:0)
您可以使用以下语法查询范围:
db.collection.find( { field: { $gt: value1, $lt: value2 } } );
在您的情况下,字段将是日期字段,此问题可以帮助您格式化值:
编辑:我没有看到检索每个第n个文档的要求。在那种情况下,我不确定MongoDB是否已经内置了支持。您可能必须自己操作返回的数组。在这种情况下,一旦获得范围,您可以按索引过滤。这里有一些样板(我无法弄清楚Array.prototype.filter的有效使用,因为该函数不需要索引 - 与你想要的相反。):
var result =[]
for (var i = 0; i < inputArray.length ; i+=3) {
result.push(numList[i]);
}
return result;