MongoDB,返回集合中每个用户的最近文档
寻找与Postgres的Distinct On类似的功能 有一个文档集合{user\u id,current\u status,date},其中status只是文本,date是日期。我还在蒙哥的早期阶段,我还没有找到最好的做事方式 mapreduce是这里最好的解决方案吗?map会发出所有信息,reduce会记录最新的一个,还是有一个内置的解决方案而不拉出mr?有一个,但是我不确定这是您需要的。Distinct是一种“查询”命令,对于大量用户,您可能希望不实时地汇总数据 Map Reduce可能是一种方法 映射阶段:您的MongoDB,返回集合中每个用户的最近文档,mongodb,mapreduce,Mongodb,Mapreduce,寻找与Postgres的Distinct On类似的功能 有一个文档集合{user\u id,current\u status,date},其中status只是文本,date是日期。我还在蒙哥的早期阶段,我还没有找到最好的做事方式 mapreduce是这里最好的解决方案吗?map会发出所有信息,reduce会记录最新的一个,还是有一个内置的解决方案而不拉出mr?有一个,但是我不确定这是您需要的。Distinct是一种“查询”命令,对于大量用户,您可能希望不实时地汇总数据 Map Reduce可能
键
将只是一个ID。您的值
将类似于以下{当前状态:'blah',日期:1234}
减少阶段:给定一个值数组,您将获取最近的值并仅返回它
为了使这项工作达到最佳效果,您可能需要查看1.8.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);
实现相同结果的另一种方法是使用
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 : "" }
})
db.coll.group({key:{user\u id:true},
reduce:函数(obj,prev){
如果(新日期(目标日期)<上一日期){
prev.status=obj.status;
prev.date=obj.date;
}
},
初始:{状态:}
})
但是,除非您的固定用户数量非常少,否则我坚信更好的解决方案是,如前所述,保留一个单独的集合,只包含每个用户的最新状态消息。谢谢,我认为这两种方法都值得研究,特别是re-reduce。考虑到最近的收集方法,这似乎会给插入过程增加很多开销,这是我希望避免的,因为这是我使用mongo的部分原因。我需要用我为每个id插入的id搜索/删除状态。虽然这应该不会很快,因为它已索引且集合较小,但mongo确实存在锁定整个集合以进行删除的“问题”,因此“似乎”这将是一个巨大的折衷。您可以很快地执行
upsert
。upsert
是“如果存在,更新或创建”。因此没有删除或附加查询。在JS中,这看起来像下面的db.most_-recent.update({u-id:user_-id},{status:“blah”},false,true)
,检查语言驱动程序的“upsert”。是的,我记得upsert在我最后一次评论后不久。因为我有一个用户群增长得相当快,我认为最近的收集是最好的方式来做到这一点,所以我正在朝这个方向发展。谢谢你的回答,谢谢你的建议。不过,由于group不能与sharding一起使用,我将避免使用这个解决方案。