项目组数据需求,需要将Mongo库中的列按日期分组转成行的格式进行显示。Mongo群里问了下,群里热心的大佬小徐 同学果断出手相助,顺利解决了数据问题。现将内容总结梳理如下,帮助有需要的其他同学
表结构
建表语句
db.class.insertMany( [
{ studentId: 1, class: "CLASS ONE", subject: "English", SCORE: 90 },
{ studentId: 1, class: "CLASS ONE", subject: "Math", SCORE: 100 },
{ studentId: 1, class: "CLASS ONE", subject: "PE", SCORE: 40 },
{ studentId: 2, class: "CLASS ONE", subject: "PE", SCORE: 80 },
{ studentId: 2, class: "CLASS ONE", subject: "English", SCORE: 95 },
{ studentId: 2, class: "CLASS ONE", subject: "Math", SCORE: 100 }
] )
表结构截图
期望数据展示
class | studentId | Enlish | Math | PE |
---|---|---|---|---|
CLASS ONE | 1 | 90 | 100 | 40 |
CLASS ONE | 2 | 95 | 100 | 80 |
查询语句
1. addFields方法
思路分为以下几步
(1)用addFields方法增加一个字段obj,用来存放学科和分数对象
(2)用学生ID进行分组,并将学生的所有的obj对象放到一个数组里
(3)将学生ID信息也以键值对的形式合并到数组中进行展现
(4)替换掉所有k,v形式,将上述的数组对象Item2以对象的形式展现
完整的查询语句如下所示
db.class.aggregate([
{ $addFields: { obj: { k: "$subject", v: "$SCORE" } } },
{ $group: { _id: "$studentId", item: { $push: "$obj" } } },
{
$project: {
item2: {
$concatArrays: [[{ k: "studentId", v: "$_id" }
], "$item"]
}
}
},
{ $replaceWith: { $arrayToObject: "$item2" } }])
2. 不用addFields方法
思路同上
(1)分组将学科和分数以数组的形式放在一个字段item中
(2)将学生ID信息放到数组item中里,返回一个新的数组对象item2
(3) 将item2数组转对对象文档,将通过replaceWith将其k,v替换成字段和值的形式展现
db.class.aggregate([
{ $group: { _id: "$studentId", item: { $push: { k: "$subject", v: "$SCORE" } } } },
{ $project: { item2: { $concatArrays: [[{ k: "_id", v: "$_id" }], "$item"] } } },
{ $replaceWith: { $arrayToObject: "$item2" } }])
3
思路:
(1)用学生ID分组,将学科分值合并成一个数组并将其放到数组对象item中
(2) 将学生ID信息合并到item中,组成新的数组对象item2
(3)将数组对象item2以对象的形式展示,并通过replaceWith函数替换字段值的方式展示结果
db.class.aggregate([
{ $group: { _id: "$studentId", item: { $push: { "$concatArrays": [["$subject"], ["$SCORE"]] } } } },
{ $project: { item2: { $concatArrays: [[["_id", "$_id"]], "$item"] } } },
{ $replaceWith: { $arrayToObject: "$item2" } }
])
下面小尝试了下mapReduce
查询每个学生的总分
db.class.mapReduce(
function() { emit(this.studentId, this.SCORE) } // map 函数
, function(key, value) { return Array.sum(value) }, //reduce函数
{
out: "test.classTotalScore"
})
db.test.classTotalScore.find()