【问题标题】:Taking sum/average of columns in mongoosejs在 mongoosejs 中取列的总和/平均值
【发布时间】:2012-10-18 20:51:50
【问题描述】:

我有一个 MongoDB 集合“标记”,其中包含字段 student_id、主题、标记。 我想要特定学生得分的平均值。 我的项目在 NodeJs 中,我正在使用 MongooseJS 进行对象建模。 如何使用 MMongooseJS 查询 this?

示例

     Student_id   Subject  Mark
     111          AAA      9
     111          BBB      5
     111          CCC      7
     222          AAA      10
     222          CCC      6
     222          BBB      8

我想要学生(id) 111 的平均分数,即((9+5+7)/3)=7)

【问题讨论】:

    标签: javascript node.js mongodb mongoose


    【解决方案1】:

    如果您使用的是 MongoDB 2.2,则可以为此使用聚合框架:

    var Mark = mongoose.model('mark', new Schema({
        Student_id: Number,
        Subject: String,
        Mark: Number
    }));
    
    Mark.aggregate([
            { $group: {
                _id: '$Student_id',
                markAvg: { $avg: '$Mark'}
            }}
        ], function (err, results) {
            if (err) {
                console.error(err);
            } else {
                console.log(results);
            }
        }
    );
    

    输出:

    [ { _id: 222, markAvg: 8 }, { _id: 111, markAvg: 7 } ]
    

    【讨论】:

    • 我试过了,但是出错了—— 500 TypeError: Object # has no method 'setMaxListeners' at Object.Document 另一件事我的 MONGODB 版本是 2.0.5 。另外,我的模型和控制器是单独的“js”文件。我将模型称为模型.model_name.aggregate([ { $group:..... 这就是我在控制器中编写代码的方式。你能告诉我为什么吗发生此错误
    • 这是错误 --500 TypeError: Object # has no method 'setMaxListeners' at Object.Document (D:\MED_NETWRK\medinfo.api\node_modules\mongoose\lib\document. js:30:8) 在 Object.Model (D:\MED_NETWRK\medinfo.api\node_modules\mongoose\lib\model.js:26:12) 在 Object.model [作为医生] (D:\MED_NETWRK\medinfo. api\node_modules\mongoose\lib\model.js:910:11) 在 controller.getDoctor (D:\MED_NETWRK\medinfo.api\controllers\DoctorController.js:54:20) 在回调 (D:\MED_NETWRK\medinfo. api\node_modules\express\lib\router\index.js:272:11)... 以及更多行。
    • @dany 那是因为您使用的是 MongoDB 2.0.5,但聚合框架需要 2.2+。可以升级到 2.2 吗?
    • 我一次只需要一个学生的平均分。即我通过了student_id -111,我想回答7.如何做到这一点?
    • 为此,将$match 元素添加到aggregate 管道的开头:{ $match: { Student_id: 111 } }
    【解决方案2】:

    这听起来像是 MongoDB 中 Map/Reduce 操作的典型示例。

    您要做的是首先运行一个映射步骤,在该步骤中您发出属于学生 id 111 的所有成绩。 然后运行求平均值的 reduce 步骤。

    monogdb 代码应如下所示:

    var map = function() {
      emit(this.Student_id, this.Mark);
    }
    var reduce = function(key, values) {
      var result = { studentid: key, mark_sum: 0, count: 0, avg_mark: 0 };
      values.forEach(function(v) {
        r.mark_sum += v;
        r.count += 1;
      });
      return r;
    }
    
    var finalize = function(key, value) {
      if (value.count > 0) {
        value.avg_mark = value.mark_sum / value.count;
      }
      return value;
    }
    

    以及mapReduce在Mongo语法中的执行:

    var command = db.runCommand( { mapreduce:"<your collection>",
                      map: map,
                      reduce: reduce,
                      query: { Student_id: 111 },
                      out: { reduce: "session_stat" },
                      finalize: finalize
                    });
    

    map_reduce 的结果被写入session_stat。在哪里可以查询。

    要了解如何在 Mongoose 中使用 MapReduce,请查看此问题:mongoose mapreduce()

    【讨论】:

    • 谢谢。但我是初学者,所以我不完全理解如何将其作为 Mongoose 查询。
    • 我在 SO 上参考了 Mongoose 的 MapReduce 问题来编辑答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多