当前位置:  开发笔记 > 数据库 > 正文

MongoDB映射/减少多个集合?

如何解决《MongoDB映射/减少多个集合?》经验,为你挑选了1个好方法。

一,背景.我曾经有一个集合,logs并使用map/reduce来生成各种报告.这些报告中的大多数是基于一天内的数据,所以我总是有一个条件d: SOME_DATE.当logs集合变得非常大时,插入变得极其缓慢(比我们监视的应用程序生成日志的速度慢),即使在丢弃大量索引之后也是如此.所以我们决定将每一天的数据放在一个单独的集合中 - logs_YYYY-mm-dd这样索引就更小了,我们甚至不需要索引日期.这很酷,因为大多数报告(因此map/reduce)都是每日数据.但是,我们有一份报告,我们需要覆盖多天.

而现在的问题.有没有办法在多个集合上运行map/reduce(或更确切地说,地图),就好像它只是一个?



1> Niels van de..:

可以使用键和所有相应的值调用reduce函数一次(但仅当键有多个值时 - 如果键只有1个值,则根本不会调用它).

它也可以被多次调用,每次都使用一个键,只有相应值的一个子集,以及之前的该键的减少结果.此方案称为重新减少.为了支持重新减少,你的reduce函数应该是幂等的.

幂等减少函数有两个关键特性:

reduce函数的返回值它所接受的值的格式相同.因此,如果reduce函数接受字符串数组,则该函数应返回一个字符串.如果它接受具有多个属性的对象,则它应返回包含这些属性的对象.这可以确保在使用先前reduce的结果调用函数时函数不会中断.

不要根据所接受的值的数量进行假设.不能保证values参数包含给定键的所有值.因此,values.length在计算中使用是非常危险的,应该避免.

更新:在最近的MongoDB版本中,不需要以下两个步骤(甚至可能,我没有检查过).如果您在map-reduce 选项中指定输出集合,它现在可以为您处理这些步骤:

{ out: { reduce: "tempResult" } }

如果你的reduce函数是幂等的,你应该没有任何问题地图减少多个集合.只需重新减少每个集合的结果:

步骤1

对每个必需的集合运行map-reduce,并将结果保存在单个临时集合中.您可以使用finalize函数存储结果:

finalize = function (key, value) {
  db.tempResult.save({ _id: key, value: value });
}

db.someCollection.mapReduce(map, reduce, { finalize: finalize })
db.anotherCollection.mapReduce(map, reduce, { finalize: finalize })

第2步

使用相同的reduce函数在临时集合上运行另一个map-reduce .map函数是一个简单的函数,用于从临时集合中选择键和值:

map = function () {
  emit(this._id, this.value);
}

db.tempResult.mapReduce(map, reduce)

第二个map-reduce基本上是一个重新减少,应该为您提供所需的结果.


现在在1.8中你可以像你提到的那样使用{out:{reduce:'collectionName'}}.它非常适合逐步聚合统计数据.查看本教程:http://kylebanker.com/blog/2009/12/mongodb-map-reduce-basics/
推荐阅读
周扒pi
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有