在 mongo 中,如何使用 Map Reduce 来按最近排序来获取组

2024-05-02

我看到的 MapReduce 示例使用了诸如 count 之类的聚合函数,但是使用 MapReduce 来获取每个类别中前 3 个项目的最佳方法是什么。

我假设我也可以使用 group 函数,但很好奇,因为他们声明分片环境不能使用 group()。然而,我实际上也有兴趣查看 group() 示例。


为了简单起见,我假设您有以下形式的文档:

{category: <int>, score: <int>}

我创建了 1000 个文档,涵盖 100 个类别,其中包括:

for (var i=0; i<1000; i++) {
  db.foo.save({
    category: parseInt(Math.random() * 100),
    score: parseInt(Math.random() * 100)
  });
}

我们的映射器非常简单,只需发出类别作为键,并发送一个包含分数数组的对象作为值:

mapper = function () {
  emit(this.category, {top:[this.score]});
}

MongoDB的reducer不能返回数组,并且reducer的输出必须与我们的值类型相同emit,所以我们必须将它包装在一个对象中。我们需要一个分数数组,因为这将使我们的减速器计算前 3 个分数:

reducer = function (key, values) {
  var scores = [];
  values.forEach(
    function (obj) {
      obj.top.forEach(
        function (score) {
          scores[scores.length] = score;
      });
  });
  scores.sort();
  scores.reverse();
  return {top:scores.slice(0, 3)};
}

最后,调用map-reduce:

db.foo.mapReduce(mapper, reducer, "top_foos");

现在我们有一个集合,其中每个类别包含一个文档,以及所有文档中得分最高的 3 个文档foo在该类别中:

{ "_id" : 0, "value" : { "top" : [ 93, 89, 86 ] } }
{ "_id" : 1, "value" : { "top" : [ 82, 65, 6 ] } }

(如果您使用相同的值,您的确切值可能会有所不同Math.random()数据生成器如我上面所示)

您现在可以使用它来查询foo对于具有最高分数的实际文档:

function find_top_scores(categories) {
  var query = [];
  db.top_foos.find({_id:{$in:categories}}).forEach(
    function (topscores) {
      query[query.length] = {
        category:topscores._id,
        score:{$in:topscores.value.top}
      };
  });
  return db.foo.find({$or:query});

}

此代码不会处理关系,或者更确切地说,如果存在关系,则在生成的最终游标中可能会返回超过 3 个文档find_top_scores.

解决方案使用group有点类似,尽管减速器一次只需考虑两个文档,而不是键的分数数组。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 mongo 中,如何使用 Map Reduce 来按最近排序来获取组 的相关文章

随机推荐