直接查询MongoDB mapreduce与更新原始集合的结果

时间:2012-02-01 15:41:58

标签: mongodb mapreduce

我有一个mapreduce作业,可以在一系列帖子上运行并计算每个帖子的受欢迎程度。 mapreduce输出一个包含每个帖子的post_id和流行度的集合。应用程序需要能够按流行度排序。有数百万个帖子,这些流行度每10分钟更新一次。我能想到的两种方法:

方法1

  1. 在帖子表人气字段
  2. 上保留一个索引
  3. 在posts表上运行mapreduce(这将替换以前的mapreduce结果)
  4. 循环遍历mapreduce结果集合中的每一行,并在posts表中单独更新其相应帖子的受欢迎程度
  5. 直接在posts表上查询以获取按人气排序的帖子
  6. 方法2

    1. 在posts表上运行mapreduce(这将取代之前的mapreduce结果)
    2. 在生成的mapreduce集合中为热门程序字段添加索引
    3. 当应用程序需要帖子时,首先查询mapreduce结果集合以获取已排序的post_id,然后查询posts集合以获取实际的帖子数据
    4. 问题

      1. 方法1需要在posts表中维护一个流行度的索引。它还需要每10分钟左右单独更新数百万(邮局表有数百万行)的流行度。它只会更新那些已经改变了流行度的帖子,但它仍然会对带有几个索引的集合进行大量更新。此集合上还会有大量的读取数据。这是可扩展的吗?
      2. 对于方法2,是否可以mapreduce posts collection以创建新的热门集合,立即在其上创建索引并查询它?
      3. 问题#2是否存在并发问题,假设应用程序将查询该流行度集合,因为它正在通过地图更新并重新编制索引。
      4. 如果mapreduce取代了流行度集合,我每次都需要手动创建一个新索引,或者mongo知道如何在流行度字段上保留一个索引。基本上,索引如何与mapreduce结果集合一起使用。
      5. 我可以使用一些调整或其他方法吗?
      6. 感谢您的帮助!

1 个答案:

答案 0 :(得分:7)

有关Map Reduce的一般建议是让您的应用程序对每个插入执行一些额外的计算,并尽可能避免执行处理器密集型映射减少作业。

是否可以在每个“帖子”文档中添加“热门程度”字段,并且每次发布每个帖子,点击,投票或测量人气时,您的应用程序都会增加它?然后,您可以索引受欢迎程度字段,按受欢迎程度搜索帖子将是闪电般快速的。

如果只是增加“流行度”字段不是一个选项,并且必须执行MapReduce操作,请尝试阻止它遍历集合中的所有文档。随着收藏的增长,你会发现这变得非常缓慢。听起来好像你的收藏已经很大了。

可以执行增量映射缩减,其中最新映射缩减的结果与前一个映射的结果集成,而不是仅仅被覆盖。您还可以向mapReduce函数提供查询,因此不会读取所有文档。也许添加一个查询,该查询仅匹配自上次地图缩小以来已查看,投票或添加的帖子。

有关增量mapReduce操作的文档如下: http://www.mongodb.org/display/DOCS/MapReduce#MapReduce-IncrementalMapreduce

“输出选项”部分介绍了将新结果与旧结果进行整合。

我知道到目前为止我的建议非常普遍,所以我现在会尝试解决你的问题:

1)如上所述,如果您的MapReduce操作必须读取每个文档,这将无法很好地扩展。
2)MapReduce操作仅输出集合。创建索引并查询该集合必须以编程方式完成。 3)如果有一个进程在另一个正在更新它的同时查询集合,则查询可以在更新之前返回文档。简短的回答是,“是的” 4)如果删除了集合,则必须重建索引。如果集合中的文档被删除,但集合本身未被删除,则索引将保持不变。如果使用{out:{replace:“output”}}选项运行MapReduce,则索引(ex)将保持不变,并且不必重新创建。
5)如上所述,如果可能的话,最好在“posts”集合中添加另一个字段,并更新它,而不是执行如此多的MapReduce操作。

希望我能够在构建应用程序时为您提供一些其他因素。最终,重要的是要记住每个应用程序都是独一无二的,因此,为了最终证明哪种方式是“最佳”,您将不得不尝试所有不同的选项,并自己决定哪种方式最有效。祝你好运!