【问题标题】:MongoDB/Mongoose: Can't put simplest MapReduce to workMongoDB/Mongoose:不能让最简单的 MapReduce 工作
【发布时间】:2012-09-26 11:18:03
【问题描述】:

您好,我要做的就是获取每个不同部门类型的计数:

fnMap = function() { 
  emit(this.departments.departmentType, {typeCount:1} ); 
} 

fnReduce = function(key, values) { 
  var result = {typeCount: 0}; 
  values.forEach(function(value) {
    result.typeCount += value.brandCount;
  });

  return result;             
};


var command = {
mapreduce : "clients", 
query     : {"departments.departmentType": {$exists: true}},
map       : fnMap.toString(), 
reduce    : fnReduce.toString(),    
    //sort: {"departments.departmentType":1}, 
    out: {inline: 1}   
};

mongoose.connection.db.executeDbCommand(command, function(err, dbres) {

    }); 

执行该命令时,dbres.documents[0].results 仅包含 1 个项目的部门类型总数,而不是每个部门类型一个及其计数的多个项目。

任何想法我做错了什么?

另外,当我取消注释 SORT 行时,我收到错误“db assertion failure: could not create cursor over...”,我相信字段名称写正确。

【问题讨论】:

  • reduce 中的brandCount 是什么?看起来像一个错字。应该是 typeCount
  • 我会在我的答案中添加更正后的 mapReduce,以防万一它有帮助,但您在这里不需要 mapReduce。

标签: mongodb mapreduce grouping mongoose


【解决方案1】:

你可以使用:

db.clients.distinct("departments.departmentType")

这将给出一个包含所有不同部门类型值的数组。

您的 map/reduce 中有两个问题。一种是reduce 中的brandCount 而不是typeCount。但更重要的是,当您需要为每个部门数组元素发出一次时,您会尝试为每个文档发出一次。更正(并略微简化)的代码:

> fnMap = function () {
    this.departments.forEach(
       function (d) {
          emit(d.departmentType, 1);
       }
    );
}
> fnReduce = function (key, values) {
    var result = 0;
    values.forEach(
       function (value) {result += value;});
    return result;
}

【讨论】:

  • 感谢您的提示,感谢他们,我取得了一些进展。当我设置out:"NewCollection" 时,它成功创建了集合。但是我想将其运行为: {inline: 1} 当我这样做时,然后我尝试使用这样的结果: mongoose.connection.db.executeDbCommand(command, function(err, dbres) { dbres. find({"value":{$gte: 5}}).exec(function(err, department) { ... }); 但是我知道 find() 不是一个有效的方法。这是正确的方法吗?很抱歉在所有这些可能的解决方案之间跳来跳去,我正在尝试所有这些解决方案,但到目前为止都没有运气。谢谢。
  • 为什么没有运气?只需使用 distinct - 你不需要 map/reduce 除非你需要计数(然后使用聚合框架更容易)。如果您想要内联结果,那么它们不在任何集合中,因此您不需要查找。 inline 将返回一个包含结果文档的数组“result”的文档。
【解决方案2】:

Mongoose v3 现在有一个Model.mapreduce() 函数(see doc)

显示的完整示例是:

var o = {};
o.map = function () { emit(this.name, 1) }
o.reduce = function (k, vals) { return vals.length }
o.out = { replace: 'createdCollectionNameForResults' }
o.verbose = true;
User.mapReduce(o, function (err, model, stats) {
  console.log('map reduce took %d ms', stats.processtime)
  model.find().where('value').gt(10).exec(function (err, docs) {
    console.log(docs);
  });
})

我认为 count 的问题是因为在您的 fnReduce() 函数中,您正在获取结果,而不是在数组中显示它们。

【讨论】:

  • 您好,感谢您的回复,但我不知道您所说的“在您的 fnReduce() 函数中,您正在获取结果而不是在数组中显示它们”是什么意思。你能告诉我应该怎么做吗?我检查了 Mongoose 3 的语法,但如果问题与我的 reduce 函数有关,我认为我会遇到与现在相同的问题。谢谢
  • 嗨,我已经取得了一些进展,但还没有工作:在我之前的例子中,如果我“发出”类似 this.field1 的东西,它可以工作,按 field1 的所有不同值分组。但是,任何比第一级更深的字段都失败:this.field1.field1a 失败。知道为什么吗?
  • 我正在尝试在 shell 中运行它(没有 mongoose),你能用集合的一些示例数据更新你的问题吗?
  • 嗨,我在这里创建了一个新帖子 stackoverflow.com/questions/12753440/…>
  • 嗨,我使用聚合解决了这个问题,请看这里的帖子link 在结果中包含字段时仍然存在一些问题,所以我开了一个新线程link 谢谢大家。跨度>
猜你喜欢
  • 2019-02-04
  • 1970-01-01
  • 2019-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-18
  • 2023-01-25
  • 2011-11-01
相关资源
最近更新 更多