说名:本篇文章开始介绍 aggregate(聚合函数)、count() 合计、distinct(去除重复)、$sum(求和操作)、"$unwind"、"$out" 等操作。
MongoDB 聚合操作
MongoDB 中聚合(aggregate) 主要用于处理数据(诸如统计平均值、求和等),并返回计算后的数据结果。
前提说明
在使用 RoboMongo 的时候发现获取集合有一种新的方式(两种都是可以使用的):
// 老版本的写法
db.collection.find();
// 新版本中支持(使用 getCollection 函数获取到集合)
db.getCollection('collectionName').find({});
简介 aggregate
官网地址:https://docs.mongodb.com/manual/aggregation
"count()"
函数取得集合的数据量
官网地址:https://docs.mongodb.com/manual/reference/operator/aggregation/count/#pipe._S_count
语法
// 直接查询
db.collection.count()
// 使用 find(),find函数中可以带入条件查询
db.collection.find().count();
// 直接在 count() 中带入条件查询(不建议使用)
db.collection.count({field : key})
// 插入数据
db.scores.insert({ "_id" : 1, "subject" : "History", "score" : 88 });
db.scores.insert({ "_id" : 2, "subject" : "History", "score" : 92 });
db.scores.insert({ "_id" : 3, "subject" : "History", "score" : 97 });
db.scores.insert({ "_id" : 4, "subject" : "History", "score" : 71 });
db.scores.insert({ "_id" : 5, "subject" : "History", "score" : 79 });
db.scores.insert({ "_id" : 6, "subject" : "History", "score" : 83 });
示例
// 查询个数
> db.scores.count();
> db.scores.find().count();
示例:统计分数大于 80 的集合数据,并且将显示的字段命名分配给 passing_scorces
db.scores.aggregate([
{ $match:
{ score:
{ $gt: 80 }
}
},
{ $count :"passing_scores" }
]);
"distinct"
官方链接:https://docs.mongodb.com/manual/reference/command/distinct/index.html
这个值的是消除重复数据,就类似于我们在 SQL 中的 distinct 操作。在 MongoDB 中存在这样子的操作,但是没有直接的函数提出,只能使用 runCommand() 实现。
首先准备一点数据:
db.getCollection('inventory').insertMany([
{ "_id": 1, "dept": "A", "item": { "sku": "111", "color": "red" }, "sizes": [ "S", "M" ] },
{ "_id": 2, "dept": "A", "item": { "sku": "111", "color": "blue" }, "sizes": [ "M", "L" ] },
{ "_id": 3, "dept": "B", "item": { "sku": "222", "color": "blue" }, "sizes": "S" },
{ "_id": 4, "dept": "A", "item": { "sku": "333", "color": "black" }, "sizes": [ "S" ] }
]);
示例:在 inventory 集合中,去除重复查询 dept 的值
db.runCommand ( { distinct: "inventory", key: "dept" } );
// 返回结果
{"values" : [ "A", "B" ], "ok" : 1.0};
示例:查询字节点的数据,在 inventory 中去除重复查询 item 节点下的 sku 的值
db.runCommand ( { distinct: "inventory", key: "item.sku" } );
// 返回结果
{"values" : [ "111", "222", "333"],"ok" : 1.0}
"$sum"
$sum 进行求和操作。
官方地址:https://docs.mongodb.com/manual/reference/operator/aggregation/sum/#grp._S_sum
在后面介绍 "$group" 的时候还会 $sum 操作,这里介绍下另外一种操作。
准备数据如下:
{ "_id": 1, "quizzes": [ 10, 6, 7 ], "labs": [ 5, 8 ], "final": 80, "midterm": 75 }
{ "_id": 2, "quizzes": [ 9, 10 ], "labs": [ 8, 8 ], "final": 95, "midterm": 80 }
{ "_id": 3, "quizzes": [ 4, 5, 5 ], "labs": [ 6, 5 ], "final": 78, "midterm": 70 }
使用在 $project 层级里面的 $sum 操作
// 对明细数据求和(对"quizzes"、"labs"),以及对 "final" 与 "midterm" 做相加求和
db.students.aggregate([
{
$project: {
quizTotal: { $sum: "$quizzes"},
labTotal: { $sum: "$labs" },
examTotal: { $sum: [ "$final", "$midterm" ] }
}
}
]);
// 返回结果
{ "_id" : 1, "quizTotal" : 23, "labTotal" : 13, "examTotal" : 155 }
{ "_id" : 2, "quizTotal" : 19, "labTotal" : 16, "examTotal" : 175 }
{ "_id" : 3, "quizTotal" : 14, "labTotal" : 11, "examTotal" : 148 }
"$unwind"
$unwind 可以将返回的数组数据,转换为字符串显示。数据使用的是"distinct" 中的数据
db.getCollection('inventory').aggregate([
{"$unwind": "$sizes"}
]);
// 返回结果
{ "_id" : 1, "dept" : "A", "item" : { "sku" : "111", "color" : "red" }, "sizes": "S" }
{ "_id" : 1, "dept" : "A", "item" : { "sku" : "111", "color" : "red" }, "sizes": "M" }
{ "_id" : 2, "dept" : "A", "item" : { "sku" : "111", "color" : "blue" }, "sizes": "M" }
{ "_id" : 2, "dept" : "A", "item" : { "sku" : "111", "color" : "blue" }, "sizes": "L" }
{ "_id" : 3, "dept" : "B", "item" : { "sku" : "222", "color" : "blue" }, "sizes": "S" }
{ "_id" : 4, "dept" : "A", "item" : { "sku" : "333", "color" : "black" }, "sizes" : "S" }
"$out"
利用此操作可以将查询结果输出到指定的结果里。类似于我们在 SQL 做数据部分的复制备份。
使用的是 $sum 中的数据:
// 查询数据
db.students.find();
示例:将 students 中的数据复制到 students_bak 中:
// $project 中是选择需要备份过去的字段
db.students.aggregate([
{ $project: {"quizzes": 1, "labs": 1, final: 1} },
{ $out: "students_bak" }
]);
// 查询刚刚备份的数据
db.students_bak.find();
从上面的操作可以看到,如果没有子啊 $project 中指明出 _id 字段,这个字段会自己复制过去。就类似于以下操作:
db.students.aggregate([
{ $project: {"_id": 1, "quizzes": 1, "labs": 1, final: 1} },
{ $out: "students_bak" }
]);
示例:测试备份出 _id 字段
// $project 中是选择需要备份过去的字段
db.students.aggregate([
{ $project: { "_id" : 0, "quizzes": 1, "labs": 1, "final": 1} },
{ $out: "students_info" }
]);
// 查询刚刚备份的数据
db.students_info.find();
如果我们指明不用备份 _id ,在复制的时候,就会自己创建出 _id 字段。