我有几个文档看起来像这样:
{
'page_id': 123131,
'timestamp': ISODate('2014-06-10T12:13:59'),
'processed': false
}
文档有其他字段,但这些是唯一与此目的相关的字段。在这个集合上还有这些文档的索引:
{
'page_id': 1
'timestamp': -1
}
我运行一个mapreduce,它返回不同的(page_id, day)
结果,其中day
是时间戳的日期部分(在上面,它将是2014-06-10
)。
这是通过下面的mapreduce完成的:
function() {
emit({
site_id: this.page_id,
day: Date.UTC(this.timestamp.getUTCFullYear(),
this.timestamp.getUTCMonth(),
this.timestamp.getUTCDate())
}, {
count: 1
});
}
reduce-function基本上只是返回{ count: 1 }
,因为我对数字不感兴趣,只是唯一的元组。
我希望能更有效率。我尝试添加sort: { 'page_id' }
,但它触发了一个错误-谷歌显示,我显然只能排序的关键,但因为这不是一个"原始"的关键是如何工作的?
还有,这个mapreduce有没有更快的替代方案?我知道mongodb有distinct
,但从我可以收集它只适用于一个领域。group
聚合函数是否相关?
聚合框架似乎更合适,因为它在本机代码中运行,而mapReduce在JavaScript解释器实例下运行。MapReduce有它的用途,但一般来说,聚合框架应该最适合于不需要特定处理的普通任务,只有JavaScript方法允许所需的控制:
db.collection.aggregate([
{ "$group": {
"_id": {
"page": "$page_id",
"day": {
"year": { "$year": "$timestamp" },
"month": { "$month": "$timestamp" },
"day": { "$dayOfMonth": "$timestamp" },
}
},
"count": { "$sum": 1 }
}}
])
这在很大程度上使用了日期聚合操作符。更多细节请参见其他聚合框架操作符。
当然,如果你想对那些唯一的日期进行反向排序(这与mapReduce将做的相反)或其他字段,那么只需在管道的末尾添加 $sort
即可:
db.collection.aggregate([
{ "$group": {
"_id": {
"page": "$page_id",
"day": {
"year": { "$year": "$timestamp" },
"month": { "$month": "$timestamp" },
"day": { "$dayOfMonth": "$timestamp" },
}
},
"count": { "$sum": 1 }
}},
{ "$sort": {
"day.year": -1, "day.month": -1, "day.day": -1
}}
])
您可能需要查看聚合框架。
查询如下:
collection.aggregate([
{$group:
{
_id: {
year: { $year: [ "$timestamp" ] },
month: { $month: [ "$timestamp" ] },
day: { $dayOfMonth: [ "$timestamp" ] },
pageId: "$page_id"
}
}
])
将为您提供您正在查找的所有字段的唯一组合。