【问题标题】:mongodb aggregation: average and sortingmongodb聚合:平均和排序
【发布时间】:2015-03-29 05:43:38
【问题描述】:

我是一个新手,对 mongodb 聚合有疑问。我用过猫鼬。

var SubjectScore = new Schema({
    name: {type:String, required:true}, //math, science, history, ...
    score: {type:Number, required:true } // 95, 85, 77,....
});

var Subject = new Schema({
    year: Number,  //2012, 2013, 2014
    subjectScore : [SubjectScore]
});

var StudentSchema = new Schema({
    name: String,
    subject: [Subject], //array length varies for each student
    profile: String,
});

所以,输入数据是这样的。

{ _id: 54c921aaa7918d4e4a8c7e51, 
  name: John, 
  profile: "He is nice",
  subject: [{ year: 2010, 
              subjectScore: [{ name:"history" score:66},
                            { name:"math", score:65},
                            { name:"science", score:87}] }]
            },{ year: 2011, 
              subjectScore: [{ name:"history" score:75},
                            { name:"math", score:61},
                            { name:"science", score:92}] }]
            },{ year: 2012, 
              subjectScore: [{ name:"history" score:83},
                            { name:"math", score:82},
                            { name:"science", score:86}] }]
            },{ year: 2013, 
              subjectScore: [{ name:"history" score:77},
                            { name:"math", score:99},
                            { name:"science", score:71}] }]
            }]
}

我想要得到的最终结果如下。

[
{ _id: "54c921aaa7918d4e4a8c7e51", 
   name: "John"
   profile: "He is nice",
   avgScore: [ 
              {name: "math", score: 77}, 
              {name:"history", score:78},
              {name:"science", score:86}  ]
   totalAvg: 82
},
{ _id: "54c921aaa7918d4e4a8c7e5b", 
   name: "Mary"
   profile: "She is kind",
   avgScore: [ 
              {name: "math", score: 67}, 
              {name:"history", score:99},
              {name:"science", score:96}  ]
   totalAvg: 82
},
{ _id: "54c921aaa7918d4e4a8c7e56", 
   name: "Jane"
   profile: "She is smart",
   avgScore: [ 
              {name: "math", score: 99}, 
              {name:"history", score:99},
              {name:"science", score:99}  ],
   totalAvg: 99
}
 ..... // 7 more student for first page result
]

我尝试关注,但无法获得姓名、个人资料字段。所以我需要额外的查询来获取姓名和个人资料字段并再次排序。

  {$project:{subject:1}},
  {$unwind:"$subject"},
  {$unwind:"$subject.subjectScore"},
  {$group:{_id:{studentId:"$_id", subjectName:"$subject.subjectScore.name"},
           avgScore:{$avg: "$subject.subjectScore.score"}}},
  {$group:{_id:"$_id.studentId", 
           avgScore:{$push: {name:"$_id.subjectName", score:"$avgScore"}}, 
           totalAvg:{$avg:"$avgScore"}}},
  {$sort:{totalAvg:-1}},
  {$limit:10} // for first page (students per page : 10)
  1. 我想知道如何保留聚合不需要但需要显示为结果的字段。如果不可能,我需要额外查询我想要的结果吗?

  2. 考虑到性能,还有其他方法可以获得此结果吗?

我已经为这份工作投入了几天时间并在谷歌上搜索,但没有得到答案。请帮帮我。

谢谢。

【问题讨论】:

    标签: node.js mongodb mongoose aggregation-framework


    【解决方案1】:

    您在第一次操作中丢失了信息,因为$project 仅发送subject 键的值。

    保持字段值不受聚合计算(nameprofile)影响的操作是使用$first。它只会抓取该字段的第一个值,该值应与其余字段相同。

    { $unwind: "$subject" },
    { $unwind: "$subject.subjectScore" },
    { $group: { _id: { sId: "$_id", subjectName: "$subject.subjectScore.name" },
                avgScore: { $avg: "$subject.subjectScore.score" },
                name: { $first: "$name" },
                profile: { $first: "$profile" } } },
    { $group: { _id: "$_id.sId",
                name: { $first: "$name" },
                profile: { $first: "$profile" },
                avgScore: { $push: { name: "$_id.subjectName", score: "$avgScore" } },
                totalAvg: { $avg: "$avgScore" } } }
    { $sort: { totalAvg: -1 } }, // this is sorting desc, but sample is asc?
    { $limit: 10 }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-25
      • 1970-01-01
      • 2012-10-11
      相关资源
      最近更新 更多