【问题标题】:MongoDB MapReduce unwantedly returning whole collection as resultMongoDB MapReduce 意外返回整个集合作为结果
【发布时间】:2014-02-28 02:04:01
【问题描述】:

我正在尝试使用 Map/Reduce 将部分合并到现有集合中。我的 MR 工作正常,但无法返回合并的结果。

以下是输出类型为缩减的 MR 的统计数据:

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

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

我尝试将 modified:true 标志合并到目标文档中。这样可以进行查询,只返回在目标集合中修改的文档。查询后,我将 flag 设置回 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"]
  }
}

我希望计数是:输入 = 2,发射 = 2,减少 = 0,输出 = 2

如果有一个新文档插入到写入集合中

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

那么 map-reduce 集合就是

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

然后计数是:输入 = 1,发射 = 1,减少 = 1,输出 = 2

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

【问题讨论】:

  • 那么您的问题到底是什么?也许您可以展示您尝试解决的问题、您的 mapReduce 代码以及您尝试使用的不同文档的示例。
  • 谢谢,更新够了吗?
  • 它确实显示了你想去的地方。但是只有代码显示了你是如何到达那里的以及它在哪里不足。但猜测一下,您目前无法知道哪些项目实际上在您的目标中,以确定要更新或插入的内容。
  • 是的,在文档下,它说reduce的选项是“如果输出集合已经存在,则将新结果与现有结果合并。如果现有文档与新结果具有相同的键,将reduce函数应用于新文档和现有文档,并用结果覆盖现有文档。”我认为从 MR 返回的结果应该代表合并的文档,而不是整个集合。这绝对是一个核心的实现问题。
  • 好吧,是否要发布代码取决于您。但是,除非您这样做,否则我看不到人们如何看到这超出了您的期望。毕竟这是问题的一部分。

标签: mongodb mapreduce


【解决方案1】:

问题的简述。您要合并的文档数量相对较少,但这会对整个集合进行处理。你不想要它。

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

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

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

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

  3. 运行一个修改后的 mapReduce,它接受 临时输入,并通过它和 临时目标 集合项应用您的 reduce 函数。这部分正在做您想要的工作,但只针对要更新的项目,并且在较小的集合中。

  4. 修改后,获取该输入并在您的主要目标上应用更新操作。

因此,一旦有这样的想法,那么您就有了一种解决方法,可以在 目标 中获得您想要的结果,而 输出阶段 不会做所有的抖动 em> 遍历所有的集合文件。权衡是在额外的步骤中,但收益似乎超过了一步完成所带来的性能问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-24
    • 2012-06-29
    • 1970-01-01
    • 2013-04-21
    • 2023-03-16
    • 1970-01-01
    • 2017-11-14
    • 1970-01-01
    相关资源
    最近更新 更多