首先是背景.我以前有一个集合logs,并使用map/reduce生成各种报告.大多数报告都是基于一天内的数据,所以我总是有一个条件d: SOME_DATE.当logs个集合变得非常大时,插入变得非常慢(比我们监视的应用程序生成日志(log)的速度慢),即使删除了很多索引.因此,我们决定将每天的数据放在一个单独的集合中——logs_YYYY-mm-dd——这样索引就更小了,我们甚至不需要日期索引.这很酷,因为大多数报告(因此map/reduce)都是基于日常数据的.然而,我们有一份报告,需要涵盖多天.

现在是问题.有没有一种方法可以在多个集合上运行map/reduce(或者更准确地说,map),就好像它只是一个集合一样?

推荐答案

reduce函数可以调用一次,使用一个键和all corresponding values(但仅当该键有多个值时——如果该键只有一个值,则根本不会调用它).

它也可能被调用多次,每次使用一个键,而只有一个subset of the corresponding values,以及之前针对该键的reduce结果.这个场景被称为re-reduce.为了支持re reduce,你的reduce函数应该是idempotent.

幂等约简函数有两个关键特性:

  • reduce函数的return value应该在它接受的same format as the values中.因此,如果reduce函数接受字符串数组,那么该函数应该返回一个字符串.如果它接受具有多个属性的对象,它应该返回一个包含这些相同属性的对象.这样可以确保在调用函数时,函数不会因前一次reduce的结果而中断.
  • Don't make assumptions based on the number of values.它能接受.不能保证values参数包含给定键的all个值.所以在计算中使用values.length是非常危险的,应该避免.

Update:在最近的MongoDB版本中,以下两个步骤不是必需的(甚至是可能的,我还没有判断).如果在map reduce options中指定输出集合,它现在可以为您处理以下步骤:

{ out: { reduce: "tempResult" } }

如果reduce函数是幂等函数,那么在映射多个集合时应该不会有任何问题.只需重新减少每个集合的结果:

第一步

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

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 })

第二步

在临时集合using the same reduce function上运行另一个map reduce.map函数是一个简单的函数,用于从临时集合中 Select 键和值:

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

db.tempResult.mapReduce(map, reduce)

这第二个map reduce基本上是一个re reduce,应该会提供您需要的结果.

Mongodb相关问答推荐

在单个mongo文档中组合数组与聚合

如何在MongoSH中的现有文档中插入字段

MongoDB 按日期时间字段查询 1h 间隔

根据聚合管道MongoDB Atlas触发器中的条件更新多个字段

Mongodb插入没有_id字段的文档

为什么不建议在 MongoDB 中使用服务器端存储函数?

ZonedDateTime 与 MongoDB

Spring Mongo 条件查询两次相同的字段

将 mongodb 聚合框架结果导出到新集合

如何在mongodb中删除数组的第n个元素

MongoDb:如何将附加对象插入对象集合?

REACT 获取发布请求

如何在 MongoDB Map-reduce 映射函数中使用变量

Mongo按实际上是数字的字符串值排序

获取 mongodb 中所有唯一标签的列表

在 MongoDB 中为现有用户更改密码

如何在java中删除mongodb集合中的所有文档

MongoDB 查询:字段不存在或具有特定值

我可以只获取 Cursor 对象(pymongo)中的第一项吗?

在 MongoDB 中比较日期(moment.js)