php - PHP 中的 Mongodb MapReduce

标签 php mongodb mapreduce schema nosql

首先,这是我第一次使用 Mongo...

概念:

  1. 用户能够用自然语言描述图像。
  2. 将用户输入进行划分,并将他描述的词存储在一个名为 Collection 的集合中 字。
  3. 用户必须能够浏览最常用的词并将这些词添加到他们的描述中。
  4. 系统将使用最常用的词(对于所有用户)并使用 这些词来描述图像。

我的word文档(目前)如下(例子)

{
"date": "date it was inserted"
"reported": 0,
"image_id": "image id"
"image_name": "image name"
"user": "user _id"
"word": "awesome"
}

单词将被复制,以便每个单词都可以与用户相关联...

问题:我需要执行一个 Mongo 查询,以了解最常用的不是由给定用户创建的词(用于描述图像)。 (满足上述第 3 点)

我看过 MapReduce 算法,但从我读到的内容来看,它有几个问题:

  1. 无法对结果进行排序(我可以从最常用到最不常用的顺序排序)
  2. 在数以百万计的文档中,它的处理时间可能很长。
  3. 不能限制返回结果的数量

我考虑过每天在给定时间运行一项任务,以将给定用户未用于描述给定图像的单词排名存储在文档(在不同的集合中)列表中。我必须将其限制为 300 个结果或类似的东西(关于适当限制的任何想法??)类似:

{
user_id: "the user id"
[
{word: test, count: 1000},
{word: test2, count: 980},
{word: etc, count: 300}
]
}

我发现此解决方案存在的问题是:

  1. 结果会有相当长的延迟,这是不可取的。
  2. 在为所有用户生成此文档时服务器负载可能会激增(实际上我对 Mongo 知之甚少,所以这只是一个假设)

也许我的方法没有任何意义......也许我在 Mongo 方面缺乏经验使我指出了错误的“模式设计”。

知道什么是解决此类问题的好方法吗?

抱歉发了这么大的帖子,感谢您的时间和帮助!

若昂

最佳答案

如前所述,您可以使用 group命令易于使用,但您需要在客户端对结果进行排序。此外,结果作为单个 BSON 对象返回,因此必须相当小——少于 10,000 个键,否则你会得到一个异常。

基于您的数据结构的代码示例:

db.words.group({
    key : {"word" : true},
    initial: {count : 0},
    reduce: function(obj, prev) { prev.count++},
    cond: {"user" :{ $ne : "USERNAME_TO_IGNORE"}}
})

另一种选择是使用新的 Aggregation framework ,将在 2.2 版本中发布。类似的东西应该可以工作。

db.words.aggregate({
   $match : { "user" : { "$ne" : "USERNAME_TO_IGNORE"} },
   $group : {
     _id : "$word",
     count: { $sum : 1}
   }
})

或者您仍然可以使用 MapReduce。实际上你可以限制和排序输出,因为结果是 一个集合。只需在输出上使用 .sort() 和 .limit() 即可。您也可以使用增量 map-reduce 输出选项,这将帮助您解决性能问题。看看 out MapReduce 中的参数.

下面是一个示例,它使用增量功能将现有集合与 words_usage 集合中的新数据合并:

m = function() { 
   emit(this.word, {count: 1}); 
};


r = function( key , values ){
     var sum = 0;
     values.forEach(function(doc) {
          sum += doc.count;
     });
     return {count: sum};
 };

db.runCommand({
    mapreduce : "words", 
    map : m,
    reduce : r,
    out : { reduce: "words_usage"},
    query : <query filter object>
})

# retrieve the top 10 words
db.words_usage.find().sort({"value.count" : -1}).sort({"value.count" : -1}).limit(10)

我想您可以每隔几分钟/几小时在 cron 中运行一次上述 MapReduce 命令,具体取决于您想要的结果准确度。对于更新查询条件,您可以使用单词文档创建日期。

一旦你有了系统热门词集合,你就可以为每个用户构建热门词,或者只是实时计算它们(取决于系统大小)。

关于php - PHP 中的 Mongodb MapReduce,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11181810/

相关文章:

php - 如何在 PHP 中使用 Tesseract OCR?

javascript - AJAX不会发送POST数据

node.js - 如何让 node.js 使用 mongoose 连接到 mongolab

hadoop - 超过Hadoop内存限制

python - GAE Python 上的 Mapreduce - 导致 ReducePipeline 在最终确定时发出回调?

php - 如何使用 EWZRecaptchaBundle 在单个页面上显示多个验证码?

php - if条件限制wordpress标题中的字数

mongodb - 数据库复合索引最佳实践 Mongodb

mongodb - 在 Mongodb 中,如何不受限制地获取返回的总结果数?

javascript - 在 Mongo 中重新加入拆分 MapReduce 数组