logo 范 · 拾光录
网址收集 关于作者 Github Gitee
杂文随笔5
Hexo博客:基础使用Hexo博客:Next主题Hexo博客:Next进阶使用Hexo博客:Next高级配置基于Node的WIKI管理
前端知识16
HTML常用知识CSS常用知识CSS美化checkbox复选框JavaScript常用知识JavaScript格式化时间戳JavaScript窗口宽高处理JavaScript黑夜主题切换实现方案JavaScript数字转大写简易图片查看器TypeScript基础知识Threejs基础三要素Threejs网格辅助和轨道控制器Threejs物体绘制Electron基础使用Nodejs基础知识animate.css页面动画
Vue框架19
Vite的使用及扩展Vue3父子组件Vue3使用Marked解析MarkdownMermaid图表生成库初始化页面加载动画Axios表单提交二维码解决方案NProgress加载进度条Vue3动态菜单实现Vue3使用ECharts图表Vue3处理Excel导入导出keep-alive页面缓存及setup问题Element:文件上传Element:结合Pinia实现动态菜单Element:图片上传组件Element:自定义统一弹窗组件Element:表格自定义指令控制按钮显示(鉴权)可视化大屏使用缩放适配分辨率
UniApp15
UniApp的基础使用封装网络请求工具及文件上传uni-app的开发记录微信小程序分享原生文件上传Pinia取消滚动条(兼容小程序)tabbar消息数量显示scroll-view上滑到底部加载数据状态栏高度动态设配数据共享与传递uview-plus导航栏实现背景融合Wot UIWot UI实现顶部背景图融合uni-app x
Java基础知识10
基础知识面向对象Lambda表达式常用API常用知识积累try-with-resource注解反射多线程经纬度距离计算
SpringBoot31
application配置Maven创建聚合项目全局异常处理锁机制项目启动初始化数据方式邮件功能集成原生定时任务异步集成阿里云OSS阿里OSS预签名上传基于hutool读excelJSR303WebSocketWebSocket版AI接口流式调用Smart-Doc接口文档生成器application配置信息加密雪花算法工具AOP实现请求参数脱敏思路JWT生成Token及工具类SpringBoot默认JSON与对象转换若依框架:安装使用若依框架:优化和调整文件上传若依框架:管理后台页面优化若依框架:后端接口代码优化SpringAISpringBoot实现AI接口流式调用服务启动时创建MySQL连接自建项目工程树形结构处理工具微信支付代码微信手机号登录
SpringMVC14
跨域处理拦截器RESTful风格伪前后端分离Jackson转换器调整Thymeleaf基于拦截器做权限校验AOP打印接口请求响应日志AOP打印接口请求响应耗时文件上传和回显POST请求加解密实现(AES)POST请求加解密实现(RSA+AES)参数动态校验实现方案真实IP和归属地
MyBatis8
MyBatis基本使用与配置Mapper使用相关MaBatis多数据源配置MyBatisPlus数据统计类处理方案MyBatisPlus条件查询正向工程的实现(H2)mybatis-plus-join
SpringCloud15
Netflix:微服务与搭建Netflix:服务的消费与提供Netflix:EurekaNetflix:ActuatorNetflix:RibbonNetflix:FeignNetflix:HystrixNetflix:ZuulAlibaba:简介与搭建Alibaba:Nacos注册中心Alibaba:RibbonAlibaba:OpenFeignAlibaba:Nacos配置中心Alibaba:GetewayAlibaba:Sentinel
MySQL6
MySQL基础知识MySQL多表查询与事务MySQL常用函数及解决方案MySQL视图MySQL索引安装MySQL
Redis7
Redis介绍和安装Redis配置文件Redis持久化Redis集群Redis语法基础Redis相关问题及解决方案SpringBoot集成Redis使用记录
MongoDB10
Linux安装MongoDBMongoDB基础语法MongoTemplate及SpringBoot配置MongoTemplate中Update操作MongoTemplate中聚合查询MongoTemplate日期归档示例项目使用相关知识归纳地理位置存储与距离查询MongoDB副本集与事务获取类名和属性名工具类
其他数据库1
H2数据库
Python编程6
Python基础知识Python语法yolo目标检测OpenCV的使用及树莓派平台condauv
工具集合13
IDEAMavenGradleGitNginx安装Nginx配置VSCodeJMeter压测DockerOllamaRustFSPicGoObs录制
Linux知识11
Linux常用命令Jar启动脚本VirtualBox安装CentOSVirtualBox安装Ubuntu树莓派安装及使用frp内网穿透ArchLinux:基础系统安装ArchLInux:图形化界面安装ArchLinux:常用软件ArchLinux:深度优化ArchLinux:Niri
创意设计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();

注意

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

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