MongoDB,为集合中的每个user_id返回最近的文档

时间:2011-02-28 21:54:05

标签: mongodb mapreduce

寻找与Postgres'Distinct On。

类似的功能

拥有一系列文件{user_id,current_status,date},其中状态只是文本,日期是日期。仍然处于早期阶段,我的头围绕着蒙戈,并感受到最佳的做事方式。

mapreduce会不会是最好的解决方案,map会全部发出,而reduce会保留最新的记录,还是有内置的解决方案而不会拉出先生?

3 个答案:

答案 0 :(得分:0)

有一个distinct command,但我不确定这是你需要的。 Distinct是一种“查询”命令,有很多用户,你可能不想实时汇总数据。

Map-Reduce可能就是这里的一种方式。

地图阶段:您的key只是一个ID。您的value类似于以下{current_status:'blah',date:1234}

减少阶段:给定一个值数组,您将获取最新值并仅返回它。

为了使这项工作达到最佳状态,您可能希望查看1.8.0中的新功能。 "re-reduce" feature。{{3}}。将允许您仅处理新数据,而不是重新处理整个状态集合。

另一种方式 这样做是为了构建一个“最新”的集合,并将状态插入与该集合联系起来。因此,当您为用户插入新状态时,您将更新其“最新”状态。

根据此功能的重要性,您可以做两件事。

答案 1 :(得分:0)

目前似乎运作良好的解决方案。

map = function () {emit(this.user.id, this.created_at);}

//We call new date just in case somethings not being stored as a date and instead just a string, cause my date gathering/inserting function is kind of stupid atm

reduce = function(key, values) { return new Date(Math.max.apply(Math, values.map(function(x){return new Date(x)})))}


res = db.statuses.mapReduce(map,reduce);

答案 2 :(得分:0)

实现相同结果的另一种方法是使用group命令,这是一种mr快捷方式,允许您聚合特定键或一组键。 在你的情况下,它将如下所示:

db.coll.group({ key : { user_id: true },
                reduce : function(obj, prev) { 
                           if (new Date(obj.date) < prev.date) { 
                             prev.status = obj.status; 
                             prev.date = obj.date; 
                           }
                         },
              initial : { status : "" }
}) 

但是,除非您拥有相当少量的固定用户,否则我坚信如前所述,更好的解决方案是保留一个单独的集合,其中仅包含每个用户的最新状态消息。