如前所述,您可以使用易于使用的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输出选项,它将帮助您解决性能问题。查看MapReduce中的out参数。
Bellow是一个例子,它使用增量功能将现有集合与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 :
})
# retrieve the top 10 words
db.words_usage.find().sort({"value.count" : -1}).sort({"value.count" : -1}).limit(10)我想你可以每隔几分钟/小时在一个cron中运行上面的MapReduce命令,这取决于你想要的结果。对于更新查询条件,您可以使用单词文档创建日期。
一旦你有系统顶部单词集合,你可以构建每个用户的顶部单词或只是实时计算它们(取决于系统大小)。