繁体   English   中英

mongodb聚合:平均值和排序

[英]mongodb aggregation: average and sorting

我是一个新手,对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
]

我尝试了以下操作,但找不到名称profile的字段。 因此,我需要其他查询来获取名称和配置文件字段并再次进行排序。

  {$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. 考虑性能,是否还有另一种方法来获得此结果?

我已经花了几天时间来完成这项工作并进行谷歌搜索,但没有得到答案。 请帮帮我。

谢谢。

因为$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 }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM