MongoDB学习(五)mongodb终极查询-Aggregate

MongoDB 学习

第一章: MongoDB学习(一) 详细安装教程 win10

第二章:MongoDB学习(二)sql语法

第三章:MongoDB学习(三)SpringBoot整合MongoDB

第四章:MongoDB学习(四)mongodb高级查询-Query/Criteria

第五章: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 );
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值