MongoDB 学习
第一章: MongoDB学习(一) 详细安装教程 win10
第三章:MongoDB学习(三)SpringBoot整合MongoDB
第四章:MongoDB学习(四)mongodb高级查询-Query/Criteria
第五章:MongoDB学习(五)mongodb终极查询-Aggregate
MongoDB学习(五)mongodb终极查询-Aggregate
Aggregate真的是超级好用,以至于后来在项目开发过程中,除了findAll和findOne,我全部都用Aggregate来实现。
Aggregate
db.collection.aggregate(AGGREGATE_OPERATION);
例如:
db.collection.aggregate([
{
$match:{
"age":{$in:[7,8]},
"name":{$regex:".*?小红.*"}
}
},
{
$group: {
"_id":"$class",
"student":{$addToSet:{"name":"$name","age":"$age"}}
}
},
{
$sort: {
"_id": 1
}
},
{
$limit: 1
}
]);
Aggregate的几个函数
管道的概念
管道在Unix和Linux中一般用于将当前命令的输出结果作为下一个命令的参数。
MongoDB的聚合管道将MongoDB文档在一个管道处理完毕后将结果传递给下一个管道处理。管道操作是可以重复的。
有点类似于java的stream流。
函数
函数 | 功能描述 |
---|---|
$project | 指定返回字段 |
$lookup | 多表关联 |
$unwind | 数组拆分 |
$match | 筛选条件 |
$sort | 排序 |
$limit | 分页 |
$skip | 跳过 |
$group | 根据id(可自定义)分组 |
$sum | 分组后求和 |
$first | 分组后取第一条 |
$last | 分组后取最后一条 |
$addToSet | 分组后添加到list |
$cond | 可以做 if-else |
几种使用场景
分组求和($group)
// 求总数(每个班级有多少同学)
db.collection.aggregate([
{
$group: {
"_id":"$class",
"count":{$sum:1}
}
}
]);
//自定义分组id(对某个对象进行分组)
db.student.aggregate([
{
$group: {
"_id":{
"class":"$class",
"name":"$name"
},
"count":{$sum:1}
}
}
]);
// 对某个字段求和
db.collection.aggregate([
{
$group: {
"_id":"$class",
"count":{$sum:"$age"}
}
}
]);
java代码
Aggregation aggregation = Aggregation.newAggregation(
Aggregation.group("class"),
Aggregation.count().as("count")
);
Aggregation aggregation = Aggregation.newAggregation(
Aggregation.group("class","name"),
Aggregation.count().as("count")
);
Aggregation aggregation = Aggregation.newAggregation(
Aggregation.group("class").sum("age").as("count")
);
List<Map> mappedResults = mongoTemplate.aggregate(aggregation, "Student", Map.class).getMappedResults();
log.info("---------mappedResults---------------"+mappedResults );
判断某个元素的值并计数($cond)
// 按班级分组,计算成绩高于80分的人数和成绩高于90分的人数
db.student.aggregate([
{
$project: {
"_id": 0,
"class": 1,
"grade": 1,
"gt90": {
$cond: { if: { $gte: [ "$grade", 90 ] }, then: 1, else: 0 }
},
"gt80": {
$cond: { if: { $gte: [ "$grade", 80 ] }, then: 1, else: 0 }
}
}
},
{
$group: {
"_id":"$class",
"gt90":{$sum:"$gt90"},
"gt80":{$sum:"$gt80"}
}
}
]);
java代码
Cond condOperation90 = ConditionalOperators
.when(Criteria.where("grade").gte("90"))
.then(1)
.otherwise(0);
Cond condOperation80 = ConditionalOperators
.when(Criteria.where("grade").gte("80"))
.then(1)
.otherwise(0);
Aggregation.newAggregation(
Aggregation.project("class","grade").andExclude("_id")
.and(condOperation90).as("gt90").and(condOperation80).as("gt80"),
Aggregation.group("class")
.sum("gt90").as("gt90")
.sum("gt80").as("gt80")
);
List<Map> mappedResults = mongoTemplate.aggregate(aggregation, "Student", Map.class).getMappedResults();
log.info("---------mappedResults---------------"+mappedResults );
拆分数组($unwind)
// 1
{
"_id": ObjectId("62c7f0fe43050000b80002a9"),
"class": "小(一)班",
"student": [
{
"name": "小红",
"age": 7
},
{
"name": "小蓝",
"age": 8
},
{
"name": "小黄",
"age": 7
}
]
}
// 2
{
"_id": ObjectId("62c7f12143050000b80002aa"),
"class": "小(二)班",
"student": [
{
"name": "张三",
"age": 7
},
{
"name": "李四",
"age": 8
}
]
}
//查询年龄大于7岁的学生,返回学生的姓名和班级
db.class.aggregate([
{
$unwind: "$student" //将学生数组拆分,一个学生对象对应一个输出文档
},
{
$match: {
"student.age":{$gt:7}
}
},
{
$project:{
"name":"$student.name",
"class":"$class"
}
}
]);
查询结果:
java代码
Aggregation.newAggregation(
Aggregation.unwind("student"),
Aggregation.match(Criteria.where("student.age").gt(7)),
Aggregation.project("student.name","class")
);
List<Map> mappedResults = mongoTemplate.aggregate(aggregation, "Student", Map.class).getMappedResults();
log.info("---------mappedResults---------------"+mappedResults );
联表查询($lookup)
db.class.aggregate([
{
$lookup: {
"from":"student", //关联student表
"localField":"class", //class表关联字段
"foreignField":"class", //student表关联字段
"as":"student" //将student表数据集合重命名
}
}
]);
java代码
Aggregation.newAggregation(
Aggregation.lookup("student","class","class","student")
);
List<Map> mappedResults = mongoTemplate.aggregate(aggregation, "Student", Map.class).getMappedResults();
log.info("---------mappedResults---------------"+mappedResults );