首先,这是我第一次使用 Mongo...
概念:
- 用户能够用自然语言描述图像。
- 将用户输入进行划分,并将他描述的词存储在一个名为 Collection 的集合中 字。
- 用户必须能够浏览最常用的词并将这些词添加到他们的描述中。
- 系统将使用最常用的词(对于所有用户)并使用 这些词来描述图像。
我的word文档(目前)如下(例子)
{
"date": "date it was inserted"
"reported": 0,
"image_id": "image id"
"image_name": "image name"
"user": "user _id"
"word": "awesome"
}
单词将被复制,以便每个单词都可以与用户相关联...
问题:我需要执行一个 Mongo 查询,以了解最常用的不是由给定用户创建的词(用于描述图像)。 (满足上述第 3 点)
我看过 MapReduce 算法,但从我读到的内容来看,它有几个问题:
- 无法对结果进行排序(我可以从最常用到最不常用的顺序排序)
- 在数以百万计的文档中,它的处理时间可能很长。
- 不能限制返回结果的数量
我考虑过每天在给定时间运行一项任务,以将给定用户未用于描述给定图像的单词排名存储在文档(在不同的集合中)列表中。我必须将其限制为 300 个结果或类似的东西(关于适当限制的任何想法??)类似:
{
user_id: "the user id"
[
{word: test, count: 1000},
{word: test2, count: 980},
{word: etc, count: 300}
]
}
我发现此解决方案存在的问题是:
- 结果会有相当长的延迟,这是不可取的。
- 在为所有用户生成此文档时服务器负载可能会激增(实际上我对 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/