PHP中的Mongo DB MapReduce
首先这是我第一次来蒙哥 概念:PHP中的Mongo DB MapReduce,php,mongodb,mapreduce,schema,nosql,Php,Mongodb,Mapreduce,Schema,Nosql,首先这是我第一次来蒙哥 概念: 用户能够用自然语言描述图像 划分用户输入,并将他描述的单词存储在一个名为 语言 用户必须能够浏览最常用的单词,并将这些单词添加到他们的描述中 系统将使用使用最多的单词(适用于所有用户)并使用 用这些词来描述形象 我的Word文档(当前)如下(示例) 这些单词将被复制,以便每个单词都可以与一个用户关联 问题:我需要执行Mongo查询,以便知道不是由给定用户创建的最常用的单词(用于描述图像)。(符合上述第3点) 我见过MapReduce算法,但从我的阅读来看,它有几个
{
user_id: "the user id"
[
{word: test, count: 1000},
{word: test2, count: 980},
{word: etc, count: 300}
]
}
我发现此解决方案存在以下问题:
João组函数应该是
MapReduce
的一个更简单版本。您可以这样使用它来计算每个单词的总和:
db.coll.group(
{key: { a:true, b:true },
cond: { active:1 },
reduce: function(obj,prev) { prev.csum += obj.c; },
initial: { csum: 0 }
});
如前所述,您可以使用易于使用的命令,但需要在客户端对结果进行排序。此外,结果作为单个BSON对象返回,因此必须非常小–少于10000个键,否则将出现异常 基于数据结构的代码示例:
db.words.group({
key : {"word" : true},
initial: {count : 0},
reduce: function(obj, prev) { prev.count++},
cond: {"user" :{ $ne : "USERNAME_TO_IGNORE"}}
})
另一个选择是使用新版本,该版本将在2.2版本中发布。这样的办法应该行得通
db.words.aggregate({
$match : { "user" : { "$ne" : "USERNAME_TO_IGNORE"} },
$group : {
_id : "$word",
count: { $sum : 1}
}
})
或者您仍然可以使用MapReduce。实际上,您可以限制和排序输出,因为结果是
收藏。只需对输出使用.sort()和.limit()。您还可以使用增量
映射减少输出选项,这将帮助您解决性能问题。请查看中的参数
下面是一个示例,它使用增量功能将现有集合与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)
m=function(){
emit(this.word,{count:1});
};
r=功能(键、值){
var总和=0;
values.forEach(函数(doc){
总和+=单据计数;
});
返回{count:sum};
};
db.runCommand({
mapreduce:“单词”,
地图:m,
减少:r,
out:{reduce:“单词的用法”},
查询:
})
#检索前10个单词
db.words_usage.find().sort({“value.count”):-1}.sort({“value.count”):-1}.limit(10)
我想您可以每隔几分钟/小时在cron中运行上面的MapReduce命令,这取决于您想要的结果的准确性。对于更新查询条件,您可以使用单词documents creation date
一旦你有了系统top words集合,你就可以建立每个用户的top words,或者只是实时计算它们(取决于系统大小)。是的,必须在客户端进行排序这是一个很好的答案!真的很期待2.2版本。同时,我会尝试你的评论!真的很感激对不起。但是mapreduce的限制是在计算完所有内容后应用的,还是会停止对10个文档的计算?在性能方面,考虑到我将使用php对结果进行排序(至少在组案例中),您的建议是什么?该限制将在执行MapReduce后或在对集合进行排序/查找时应用。正如我所说的,您可以随时重用结果。何时以及多久更新一次集合取决于您。在性能方面,您应该可以在php端进行排序。如果将来这会成为一个问题,那就使用一些缓冲区。
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)