MongoDB MapReduce不必要地返回整个集合作为结果

时间:2014-02-28 02:04:01

标签: mongodb mapreduce

我正在尝试使用Map / Reduce来完成对现有集合的部分合并。我让MR工作正常,但是在返回合并后的结果时遇到了麻烦。

以下是MR的统计数据,输出类型为简化:

{ 
    "result" : "calculation",
    "timeMillis" : 222,
    "counts" : { 
        "input" : 492,
        "emit" : 920,
        "reduce" : 64,
        "output" : 435078
     },
    "ok" : 1.0
 }

我希望输出是实际合并的文档数,而不是整个集合。有没有办法做到这一点?

我尝试将modified:true标志合并到目标文档中。这样,可以进行查询,仅返回在目标集合中修改的文档。在查询之后,我将标志设置回false。

虽然这样可以正常工作,但由于进行了大量的更改然后向后翻转,它开始颠簸索引,因此HD速率上升,MR性能急剧下降。

理想情况下,从C#驱动程序调用result.GetResults()会自然地返回由MR修改的文档而无需使用标记。

更新

具体来说,我有一个“只写”的集合,MR运行该集合以合并为“读取”集合。

如果有类似

的文档集
{
   "_id":BsonId,
   "key":"key1",
   "valarray":["one"],
},
{
   "_id":BsonId
   "key":"key2"
   "valarray":["one"]
}

然后MR进入空白查询集合将产生

{
  "_id":"key1",
  "value":
  {
     "valarray":["one"]
  }
},
{
  "_id":"key2",
  "value":
  {
     "valarray":["one"]
  }
}

我希望计数为:input = 2,emit = 2,reduce = 0,output = 2

如果那时在写集合中插入了新文档

{
   "_id":BsonId,
   "key":"key1",
   "valarray":["two"],
}

然后map-reduce集合将是

{
  "_id":"key1",
  "value":
  {
     "valarray":["one", "two"]
  }
},
{
  "_id":"key2",
  "value":
  {
     "valarray":["one"]
  }
}

计数是:input = 1,emit = 1,reduce = 1,output = 2

通过C#驱动程序,调用result.GetResults()会遍历整个目标集合。问题是我不想迭代集合,我只想迭代目标集合中由MR修改的文档。在这种情况下,它应该返回“_id”:“key1”而不是“_id”:“key2”。

1 个答案:

答案 0 :(得分:0)

问题的果壳。您要合并的文档数量相对较少,但这对于整个集合来说是颠簸。你不想要它。

这里的问题是你想要对输入阶段产生的输出文档应用 reduce 函数,当然还要对已经存在的文档应用 reduce 函数。因此,实现似乎是在整个输出集合上运行reduce以便与结果合并。

所以你想要的是一个有针对性的结果,其中只有更新的文件才被实际修改。有一种方法我可以看到实现这一目标,但它将采取一些步骤。还有更多的代码。

  1. 运行常规mapReduce操作。但是,不要将输出定向到目标集合,而是输出到临时输入集合。

  2. 使用该输出中的键从目标中获取所需的修改文档,并将其插入临时目标集合中。

  3. 运行经过修改的mapReduce,其中包含临时输入,并通过该临时目标集合项应用 reduce 功能。这部分正在完成您想要的工作,但仅限于要更新的​​项目,以及较小的集合。

  4. 修改后,接受该输入并应用主目标上的更新操作。

  5. 所以一旦这样思考,那么你有一个解决方法可以在目标中获得你想要的结果而不用输出阶段做所有的颠簸覆盖所有收集文件。权衡是在额外的步骤,但收益似乎超过了一步到位的性能问题。