首页 文章

mongodb聚合:平均和排序

提问于
浏览
1

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

我试过跟随,但我无法得到 name, profile 的字段 . 所以我需要额外的查询来获取名称和 Profiles 字段并再次排序 .

{$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 回答

  • 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 }
    

相关问题