MongoDB映射/减少多个集合?

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

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


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

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

它也可以被调用多次,每次调用一个键,并且只调用相应值的一个子集,以及该键先前的reduce结果。这种情况称为重新还原。为了支持re-reduce,您的reduce函数应该是

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

  • reduce函数的返回值的格式应与它接收的值的格式相同。因此,如果reduce函数接受字符串数组,则该函数应返回字符串。如果它接受具有多个属性的对象,则应返回包含这些相同属性的对象。这可以确保函数在使用先前reduce的结果调用时不会中断
  • 不要根据它接受的值的数量进行假设。不能保证
    values
    参数包含给定键的所有值。因此,在计算中使用
    value.length
    是非常危险的,应该避免
更新:以下两个步骤在较新的MongoDB版本中不是必需的(甚至可能,我还没有检查)。如果您在map reduce中指定输出集合,它现在可以为您处理以下步骤:


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

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

db.tempResult.mapReduce(map, reduce)
第一步 对每个必需的集合运行map reduce,并将结果保存在单个临时集合中。您可以使用以下方法存储结果:

步骤2 使用相同的reduce函数对临时集合运行另一个map reduce。map函数是一个简单的函数,用于从临时集合中选择键和值:

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

db.tempResult.mapReduce(map, reduce)

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

我使用了
map reduce
方法。这里有一个例子

var mapemployee = function () {
    emit(this.jobid,this.Name);};

var mapdesignation = function () {
    emit(this.jobid, this.Designation);};

var reduceF = function(key, values) {
    var outs = {Name:null,Designation: null};
    values.forEach(function(v){
    if(outs.Name ==null){
   outs.Name = v.Name }
   if(outs.Name ==null){
    outs.Nesignation = v.Designation}                    
     });
    return outs;
};

result = db.employee.mapReduce(mapemployee, reduceF, {out: {reduce: 'output'}});
result = db.designation.mapReduce(mapdesignation,reduceF, {out: {reduce: 'output'}});

refreference:

如何将所有映射/减少的结果存储在一个集合中,以便以后映射/减少?@ionut bizau:您可以使用finalize函数来完成此操作。查看我的更新答案了解详细信息。太棒了,我没想过!谢谢尼尔斯,你的回答很好。但是,如果我们在两个方向上都有重复的键呢?我建议将tempResult数据保存为{id,value}在通常的id下,并使用map=function()将它们映射为reduce{emit(this.id,this.value);}Oh!我从MongoDB 1.7.4开始发现了mapReduce的有用特性{reduce:“collectionName”}-如果结果集中和旧集合中存在给定键的文档,那么将对这两个值执行reduce操作,结果将在1.8中,您可以使用{out:{reduce:'collectionName'},就像您提到的那样。它非常适合以增量方式聚合统计数据。查看本教程:
var mapemployee = function () {
    emit(this.jobid,this.Name);};

var mapdesignation = function () {
    emit(this.jobid, this.Designation);};

var reduceF = function(key, values) {
    var outs = {Name:null,Designation: null};
    values.forEach(function(v){
    if(outs.Name ==null){
   outs.Name = v.Name }
   if(outs.Name ==null){
    outs.Nesignation = v.Designation}                    
     });
    return outs;
};

result = db.employee.mapReduce(mapemployee, reduceF, {out: {reduce: 'output'}});
result = db.designation.mapReduce(mapdesignation,reduceF, {out: {reduce: 'output'}});