MongoDB、MapReduce 和排序

标签 mongodb mongodb-php mongodb-query

我可能对此有点不知所措,因为我仍在学习 MongoDB 的来龙去脉,但这里继续。

现在我正在开发一种工具来搜索/过滤数据集,按任意数据点(例如流行度)对其进行排序,然后按 id 对其进行分组。我认为我能做到这一点的唯一方法是通过 Mongo 的 MapReduce 功能。

我不能使用 .group(),因为我正在使用超过 10,000 个键,而且我还需要能够对数据集进行排序。

我的 MapReduce 代码运行良好,除了一件事:排序。排序根本不想工作。

db.runCommand({
  'mapreduce': 'products',
  'map': function() {
    emit({
      product_id: this.product_id,
      popularity: this.popularity
    }, 1);
  },
  'reduce': function(key, values) {
    var sum = 0;
    values.forEach(function(v) {
      sum += v;
    });

    return sum;  
  },
  'query': {category_id: 20},
  'out': {inline: 1},
  'sort': {popularity: -1}
});

我已经在流行度数据点上有一个降序索引,所以它肯定因为缺少它而不起作用:

{ 
  "v" : 1, 
  "key" : { "popularity" : -1 }, 
  "ns" : "app.products", 
  "name" : "popularity_-1" 
}

我只是不明白为什么它不想排序。

由于此功能的工作方式,我不能将结果集输出到另一个集合,然后对其运行 .find().sort({popularity: -1}) ,而不是内联结果集。

最佳答案

首先,Mongo map/reduce 不是为用作查询工具而设计的(就像在 CouchDB 中一样),它是为您运行后台任务而设计的。我在工作中使用它来分析流量数据。

但是,您做错的是您将 sort() 应用于您的输入,但这没有用,因为当 map() 阶段完成时,中间文档按每个。因为您的 key 是一个文档,所以它按 product_idpopularity 排序。

这就是我生成数据集的方式

function generate_dummy_data() {
    for (i=2; i < 1000000; i++) { 
        db.foobar.save({
          _id: i, 
         category_id: parseInt(Math.random() * 30), 
         popularity:    parseInt(Math.random() * 50)
        }) 
    }
}

这是我的 map/reduce 任务:

var data = db.runCommand({
  'mapreduce': 'foobar',
  'map': function() {
    emit({
      sorting: this.popularity * -1,
      product_id: this._id,
      popularity: this.popularity,
    }, 1);
  },
  'reduce': function(key, values) {
    var sum = 0;
    values.forEach(function(v) {
      sum += v;
    });

    return sum;  
  },
  'query': {category_id: 20},
  'out': {inline: 1},
});

这是最终结果(很长在这里粘贴):

http://cesarodas.com/results.txt

这是可行的,因为现在我们正在按 sorting、product_id、流行度 进行排序。您可以随心所欲地进行排序,只要记住最终排序是按 key 进行的,无论您的输入是如何排序的。

无论如何,正如我之前所说,您应该避免使用 Map/Reduce 进行查询,它是为后台处理而设计的。如果我是你,我会设计我的数据,以便我可以通过简单的查询访问它,在这种情况下,总是需要权衡复杂的插入/更新来进行简单的查询(这就是我对 MongoDB 的看法)。

关于MongoDB、MapReduce 和排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12015064/

相关文章:

mongodb - $在 mongodb 中查找多个级别

node.js - 在 mongodb 中查找具有特定字段的所有集合

mongodb - GMongo在对象的嵌入式json中搜索

node.js - 使用 Node.JS、MongoDB 和 Socket.IO 的实时多人游戏 : Game loop and async calls

php - 如何在mongodb中对查找结果进行排序

php - 在 macOS 上为 xampp 安装 mongodb 扩展

node.js - 在亚马逊 EC2 上托管 nodeJS/mongoose Web 应用程序

node.js - Mongoose:在保存时根据父字段值设置子文档字段值

php - MongoDB 和 CodeIgniter

mongodb - 如何在 Mongodb compass UI 中运行地理空间查询?