logo 范 · 拾光录
网址收集 关于作者 Github Gitee
杂文随笔4
Hexo博客:基础使用Hexo博客:Next主题Hexo博客:Next进阶使用Hexo博客:Next高级配置
前端编程3
前端基础知识16
UniApp15
Vue框架19
Java编程7
Java基础知识14
SpringBoot31
SpringMVC14
MyBatis8
SpringCloud15
RocketMQ1
MyCat1
数据库4
MySQL6
Redis7
MongoDB10
H21
Java技术栈4
知识整理分布式锁的实现方案MySQL事务MySQL的锁
软件工具箱14
IDEAGitMavenGradleNginx安装Nginx配置JMeter压测OllamaPicGoRustFSVSCodeDockerObsidianObs录制
Linux知识11
树莓派安装及使用ArchLinux:常用软件ArchLinux:基础系统安装ArchLinux:深度优化ArchLInux:图形化界面安装ArchLinux:Nirifrp内网穿透Jar启动脚本Linux常用命令VirtualBox安装CentOSVirtualBox安装Ubuntu
Python编程6
Python基础知识Python语法yolo目标检测OpenCV的使用及树莓派平台condauv
创意设计2
Blender:入门知识UI设计基础知识
AI相关9
Claude CodeHermes AgentOpenAI基本使用OpenAI工具调用OpenAI记忆管理OpenAI推理执行OpenAI开发框架Langchainllama.cpp

关联操作

Criteria criteria = new Criteria();
criteria.and("status").ne(GlobalStatus.STATUS_DELETE.value());
if (StrUtil.isNotBlank(keyword)) {
    criteria.and("customer").regex(keyword);
}
Aggregation aggregation = Aggregation.newAggregation(
    	// 查询条件
        match(criteria),
    	// 排序(可多个)
        Aggregation.sort(Sort.Direction.DESC, "_id"),
        // 跳过多少条
        Aggregation.skip((pageIndex - 1) * pageSize),
        // 查询多少条数据
    	limit(pageSize),
    	// 关联其他表(本表字段关联其他表的主键)
        lookup(UserShowInfoView.collectionName, "uid", "_id", "user0"),
        // 关联其他表(本表主键关联其他表的字段,最好给关联表的关联字段加索引,加快查询速度)
        lookup(ShopServer.COLLECTION_NAME, "_id", "shopId", "server0"),
        // 子表再次关联其他表(注意尽量设计表中带字段,该操作性能不高)
        lookup(User.COLLECTION_NAME, "$server0.uid", "_id", "user1"),
	    // 数据处理,字段过多使用Class工具类
    	project("applyStatus", "violationTag", "status", "authV", "avatar","name")
                // 更改字段名进行映射
                .and("schoolName").as("name")
                // 取关联数据的第一条数据
                .andExpression("arrayElemAt('$user0',0)").as("user")
                // 取关联数据的第一条的某个字段
                .andExpression("arrayElemAt('$authV0.authV',0)").as("authV")
                // 取关联数据的条数(数量)
                .andExpression("{$size:'$server0'}").as("serverNum")
                // 加减(减-1也可)
                .and("evaluationCount").plus(1).as("evaluationCount")
                // 除法计算
                .andExpression("{$divide:{'$goodEvaluationCount','$evaluationCount'}}").as("favourable")
                // 给null的数据赋默认值
                .and("isTopping").applyCondition(ConditionalOperators.IfNull.ifNull("isTopping").then("0"))
                // 是否存在(用于是否收藏、点赞)
                .andExpression(String.format("in(new org.bson.types.ObjectId('%s'),msgLike.uid)", uid)).as("like")
);
List<ShopAdminListVo> list = mongoTemplate.aggregate(aggregation, Shop.COLLECTION_NAME, ShopAdminListVo.class).getMappedResults();

注意:关联后的变量名称不要使用status,会报错

关联分组

Aggregation.group("uid").count().as("count")
    .first("uid").as("uid")
    .first("lawDeptId").as("lawDeptId")
Aggregation.group().sum("time").as("count")

注意:group后就剩下_id字段,且为group中的字段值,如果后面需要其他字段使用first

关联排序

// 单条件单字段
Aggregation.sort(Sort.Direction.DESC, "createDate")

// 单条件多字段
Aggregation.sort(Sort.Direction.DESC, "status", "createDate")

// 多条件
Aggregation.sort(Sort.Direction.ASC, "status").and(Sort.Direction.DESC, "createDate")

sort(new Sort(Sort.Order.asc("topType"), Sort.Order.desc("sort"), Sort.Order.desc("topDate"), Sort.Order.desc("_id"))),

// 多条件格式
Sort sort;
if (dateSort == 0) {
    sort = new Sort(Sort.Direction.DESC, "createDate");
} else {
    sort = new Sort(Sort.Direction.ASC, "createDate");
}
Aggregation aggregation = Aggregation.newAggregation(
    Aggregation.match(criteria),
    Aggregation.sort(sort)
);

关联过滤

//过滤多条件:filter
BasicDBObject filter4 = new BasicDBObject("$filter", new BasicDBObject(
		"input","$pushMessage0"
		).append("as", "item")
		.append("cond", new BasicDBObject("$and", 
				new Object[] {
						new BasicDBObject("$eq", new Object[] {"$item.classify", Constant.INTERACTION_NOTIFY_CLASSIFY}),
						new BasicDBObject("$eq", new Object[] {"$item.status", Constant.COMM_STATUS_NORMAL})
						}))
		);
BasicDBObject reserveFilter = BasicDBObject.parse("{'$filter':{'input':'$pushMessage0','as':'item','cond':{'$and':[{'$eq':['$item.classify',4]},{'$eq':['$item.status',0]}]}}}");		
//过滤单条件:filter
BasicDBObject filter = new BasicDBObject("$filter", new BasicDBObject(
					"input","$lives0"
					).append("as", "item")
					.append("cond", new BasicDBObject("$eq", 
							new Object[] {"$item.status", Constant.COMM_STATUS_NORMAL})));
BasicDBObject reserveFilter = BasicDBObject.parse("{'$filter':{'input':'$reserve0','as':'item','cond':{'$eq':['$item.status',0]}}}");
			
			Aggregation agg = newAggregation(
					geoNear(NearQuery.near(new Point(lon, lat))
							.query(query(where("_id").is(id)))
							.distanceMultiplier(Constant.EarthRadius)
							.spherical(true), "dist.dis"),//距离geoNear查询
					lookup(Camera.collectionName, "live", "_id", "lives0"), //关联查询
					lookup(UserShowInfoView.collectionName, "uid", "_id", "user0"),
					lookup(LikeRecodeView.collectionName, "_id", "oid", "like0"),
					lookup(BusinessWantGo.collectionName, "_id", "bid", "wantGo0"),
					lookup(BusinessCustomerRecord.collectionName, "_id", "bid", "customerRecode0"),
					Aggregation.graphLookup(LegalVideoType.COLLECTION_NAME)
                            .startWith("$_id")
                            .connectFrom("_id")
                            .connectTo("parentId").as("son"),
					project("status", "hot", "uid", "name", "keyWordType", "intro", "intro2"
							, "cover", "loc", "address", "doBusinessWeek", "startDoBusinessTime"
							, "endDoBusinessTime", "telphone", "createDate")
					.andExpression("dist.dis").as("dis")
					.andExpression("substr('$cityCode', 4, 2)").as("sotCityCode1")//截取字符串,从某(4)位置开始截取几(2)位;
					.and(new BaseAggregateExpression(filter)).as("live") //过滤器过来数组
					.andExpression("arrayElemAt(\"$user0\",0)").as("user") //选取数组第0个
					
					.andExpression(String.format("in(new org.bson.types.ObjectId(\"%s\"),like0.uid)", uid)).as("like") //判断是否包含
					.andExpression("{$size:'$like0'}").as("likeNum")  //统计数组长度
					
					.andExpression("{$size:'$wantGo0'}").as("wantGoNum")
					
					.andExpression("{$size:'$customerRecode0'}").as("customerRecodeNum")
					.andExpression("{$reverseArray:'$customerRecode0'}").as("customerRecode1"),//数组翻转
					
					project("status", "hot", "uid", "name", "keyWordType", "intro", "intro2"
							, "cover", "loc", "address", "doBusinessWeek", "startDoBusinessTime"
							, "endDoBusinessTime", "telphone", "createDate"
							, "live", "user", "like", "likeNum", "wantGoNum"
							, "customerRecodeNum", "dis")
					.andExpression(String.format("{slice(customerRecode1,%s)}", Constant.LIST_LIMIT_5)) //截取数组指定长度
					.as("customerRecode2"),
					lookup(UserShowInfoView.collectionName, "customerRecode2.uid", "_id", "callUsers"),
					
					project("status", "hot", "uid", "name", "keyWordType", "intro", "intro2"
							, "cover", "loc", "address", "doBusinessWeek", "startDoBusinessTime"
							, "endDoBusinessTime", "telphone", "createDate"
							, "live", "user", "like", "likeNum", "wantGoNum"
							, "customerRecodeNum", "callUsers", "dis")
					);
			BasicDBObject obj = mongoTemplate.aggregate(agg, Business.class, BasicDBObject.class).getUniqueMappedResult();	

字段计算

Aggregation aggregation = Aggregation.newAggregation(
        Aggregation.match(Criteria.where("type").in(1, 3).and("status").is(0)),
        Aggregation.project("startTime", "endTime").andExpression("endTime - startTime").as("totalTime"),
        Aggregation.group().sum("totalTime").as("totalTime")
);

层级遍历

例如多级分类等场景

Aggregation aggregation = Aggregation.newAggregation(
    Aggregation.match(criteria1),
    Aggregation.graphLookup(LegalVideoType.COLLECTION_NAME)
        .startWith("$_id")
        .connectFrom("_id")
        .connectTo("parentId").as("son"),
    Aggregation.project().andExpression("son._id").as("sonIdList")
);
    
List<Document> dbObjectList = mongoTemplate.aggregate(aggregation, LegalVideoType.COLLECTION_NAME, Document.class).getMappedResults();

注意

集合查询中如果出现关联查询,最好为关联表的外键建立索引,否则数据量大了就会比较慢

关联操作
关联分组
关联排序
关联过滤
字段计算
层级遍历
注意