springboot mongo 使用
nosql对我来说,就是用它的变动列,如果列是固定的,我为什么不用mysql这种关系型数据库呢?
所以,现在网上搜出来的大部分,用实体类去接的做法,并不适合我的需求。
所以,整理记录一下,我收集到的springboot,自由,使用mongo的信息。
目录
前置
依赖引入
配置
代码引入
使用
插入
单行插入
批量插入
查询
查询全部(无条件)
条件查询
排序
DBObject更加自由的查询
聚合
某些列有值,并且只返回选中的列,并且聚合
其他工具包,像客户端一样写查询
mongodb的java驱动MongoClient
前置
依赖引入
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
版本就根据自己的spring版本来好了,不需要额外加
配置
spring.data.mongodb.uri=mongodb://localhost:27017/myTest
我用的本地版本的mongo,没配用户名+密码,如果配了,就需要加下。
本地mongodb的安装,我使用了菜鸟 MongoDB 安装介绍,并安装了mongoDB compass客户端,用来直连查看mongodb里的数据库数据
代码引入
@Resource private MongoTemplate template;
上述配置完成后,直接依赖注入,就可以使用了
使用
插入
单行插入
template.insert(singleObject, "multi_1242");
上述代码中
singleObject 为 json字符串 {"_id": 3, "1": "1.1", "2": "2.1", "amount": 2.1}
"multi_1242" 为集合名称,我的需求是,不同的集合,里面document的键名,是会完全不同的
批量插入
boolean product = template.collectionExists("multi_1242");if (!product) {template.createCollection("multi_1242");}Gson gson = new Gson();JsonObject jsonObject = new JsonObject();jsonObject.addProperty("_id", 1);jsonObject.addProperty("1", "1.1");jsonObject.addProperty("2", "2.2");jsonObject.addProperty("amount", 10.12);// template.save(gson.toJson(jsonObject), "multi_1242");JsonObject jsonObject1 = new JsonObject();jsonObject1.addProperty("_id", 2);jsonObject1.addProperty("1", "1.2");jsonObject.addProperty("2", "2.2");jsonObject1.addProperty("3", "3.1");jsonObject1.addProperty("amount", 1.13);// template.save(gson.toJson(jsonObject1), "multi_1242");List<String> list = new ArrayList<>();list.add(gson.toJson(jsonObject));list.add(gson.toJson(jsonObject1));template.insert(list, "multi_1242");
这里我使用了google的Json化的工具包,我没有使用ali的fastjson,是因为它的JSON对象转JSON字符串曾经坑过我(它会把一些特殊字符,转换成别的字符)
<dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId><version>2.10.1</version>
</dependency>
import com.google.gson.Gson;
import com.google.gson.JsonObject;
上述动作完成插入后,mongo那边显示的结果为

从上述的实验,可以得出几个结论
1、springboot插入mongo的话,也是用json字符串去插入的,我曾经试过,直接用jsonObject类型去插入,document查出来,会有很多不需要的字段都被插进去了(这并不是我想要的),所以你想插入什么样子,就组装成什么样子后,json字符串后,再传入进去。下图为错误示范。

2、_id这个键,是默认的主键名称,如果你想控制主键多少,可以设置后,再进行插入
查询
查询全部(无条件)
Query query = new Query();
List<String> list = template.find(query, String.class, "multi_1242");//查看测试结果
LoggerUtils.info("size is " + list.size());
for (int i = 0; i < list.size(); i++) {//使用了封装类,打印了一下查出来的结果LoggerUtils.info(i + " is " + list.get(i));
}
不需要传入查询条件,传个空的query进去就行了
下图为输出结果

条件查询
2个and的查询条件
Query query = new Query();
Criteria criteria = new Criteria();
criteria.where("1").is("1.1");
criteria.and("2").is("2.1");
query.addCriteria(criteria);
List<String> list = template.find(query, String.class, "multi_1242");
查询结果

如果有的document缺少查询条件里的一些键呢,结果是如何呢? 然后我增加了一个查询条件
Query query = new Query();
Criteria criteria = new Criteria();
criteria.where("1").is("1.1");
criteria.and("2").is("2.1");
//增加一条查询条件
criteria.and("3").is("3.1");
query.addCriteria(criteria);
List<String> list = template.find(query, String.class, "multi_1242");
![]()
结果是没有查出来,如果写在where里,明确某个键=某个值的话,那么查出来的document,必然是有该键的。
但是order却不一定,为此,我多插了一行{"_id": 4, "1": "1.1", "2": "2.1","3": "3.1", "amount": 2.1}
排序
Query query = new Query();
Criteria criteria = new Criteria();
criteria.where("1").is("1.1");
criteria.and("2").is("2.1");
query.addCriteria(criteria);
//增加一条排序条件
query.with(Sort.by("3"));
List<String> list = template.find(query, String.class, "multi_1242");
结果

可以看到order依赖的属性不存在,也是可以被查出来的,并且正常排序还排在前面
DBObject更加自由的查询
上述用这个Query类构造还是束手束脚的,不过我又查到了,跟客户端类似的方法

DBObject obj = new BasicDBObject();
obj.put("1", "1.1");
obj.put("2", "2.1");
Query query = new BasicQuery(obj.toString());
List<String> list = template.find(query, String.class, "multi_1242");
仿照着写,查询结果是ok的

如果是复杂的查询,可以自己用DBObject,BasicDBList构造嵌套起来
聚合
某些列有值,并且只返回选中的列,并且聚合
如果是客户端的话,可以先过滤出来后,再进行聚合
例如,我想找到“1”列,“2”列有值,并且根据这两列进行合并的,并且返回的结果只包含这2列作为_id,意味着,如果有(1.1,2.1,3.1)和(1.1,2.1)的组合,将会合并到一起
db.multi_1242.aggregate([
#先过滤一波需要的数据
{$match:
{
"1":{$exists:true},
"2":{$exists:true}
}
},
#然后进行合并,_id使用要合并的字段组成
# mytotal这个键是我随便起的,就是group后面跟的对象,就是将会输出的数据格式
{$group:
{
_id:{"1":"$1","2":"$2"},
mytotal:{$sum:"$amount"}
}
}
])
原始数据如图

查询后的结果如下

可以看到我的_id设置的只有“1”列和“2”列,所以合并也是根据我的要求来合的。
如果我的_id加入了“3”列,那么,有的document行有3这个键值,有的没有,又该如何?
查询如下:

可以发现,有“3” 列的就有,没有“3”列的,就没有。
客户端是这样,那么如何在项目中使用聚合来查询?
Aggregation aggregation =Aggregation.newAggregation(Aggregation.match(new Criteria().where("1").is(obj1).and("2").is(obj1)),Aggregation.group("1", "2").sum("amount").as("mytotal"));
AggregationResults results = template.aggregate(aggregation, "multi_1242", String.class);
List<String> mappedResults = results.getMappedResults();
打印得到的结果

这个group查多组合,需要传 Fields
import org.springframework.data.mongodb.core.aggregation.Fields;DBObject obj1 = new BasicDBObject();
obj1.put("$exists", true);Fields fields = Fields.fields("1");
fields = fields.and("2");
fields = fields.and("3");
Aggregation aggregation =Aggregation.newAggregation(Aggregation.match(new Criteria().where("1").is(obj1).and("2").is(obj1)),Aggregation.group(fields).sum("amount").as("mytotal"));
AggregationResults results = template.aggregate(aggregation, "multi_1242", String.class);
List<String> mappedResults = results.getMappedResults();
查询结果

这个Fields还真是难造,看了下源码,才知道怎么造出来。
然后,如果不想调用各种聚合函数,比如sum,count也是可以的。
比如我把上面的聚合查询,改为这样。
Aggregation aggregation =Aggregation.newAggregation(Aggregation.match(new Criteria().where("1").is(obj1).and("2").is(obj1)),Aggregation.group(fields));
结果如下

只会查出聚合的键,这也是我需要的内容
其他工具包,像客户端一样写查询
mongodb的java驱动MongoClient
mongoClient的参考文章
其中的这种写法,我是比较赞赏的,因为都是字符串拼接,很自由,引用一下。
Document match = Document.parse("{$match:{$or:[{\"组织机构代码\":\"" + id + "\"}, {\"单位名称\":\"" + id + "\"}]}}");
Document unwind = Document.parse("{$unwind:\"$公司人员\"}");
Document group = Document.parse("{$group : {_id : \"$公司人员." + arrayFiled + "\", count : {$sum : 1}}}");List<Document> conditions = new ArrayList<>();
conditions.add(match);
conditions.add(unwind);
conditions.add(group);List<Document> result = new ArrayList<>();
AggregateIterable<Document> resultSet = this.collection.aggregate(conditions);
try (MongoCursor<Document> cursor = resultSet.iterator()) {while (cursor.hasNext()) {Document item_doc = cursor.next();result.add(item_doc);}
}
Bson的话,两种工具包好像都可以进行使用,我这边就不赘述了。
相关文章:
springboot mongo 使用
nosql对我来说,就是用它的变动列,如果列是固定的,我为什么不用mysql这种关系型数据库呢? 所以,现在网上搜出来的大部分,用实体类去接的做法,并不适合我的需求。 所以,整理记录一下…...
如何使用appuploader制作apple证书
转载:如何使用appuploader制作apple证书 如何使用appuploader制作apple证书 一.证书管理 点击首页的证书管理 二.新建证书 点击“添加”,新建一个证书文件 免费账号制作证书只有7天有效期,没有推送消息功能,推送证书…...
Promise详细版
promise基础原理到难点分析 常见的Promise的方法解读 扩展async和await深入分析 逐步分析Promise底层逻辑代码 一、Promise基础 1.什么是promise 为了解决回调地狱: //2.设置点击事件btn.onclick function() {//3.创建ajax实例化对象let xhr new XMLHttpRe…...
v-for循环生成的盒子只改变当前选中的盒子的样式
1.给盒子添加动态属性:class"[index isActive?active-box:choose-box]" <div v-for"(item,index) in zyList" :key"item.sid" :class"[index isActive?active-box:choose-box]" click"getKmList(item,index)"…...
Spring Data JPA源码
导读: 什么是Spring Data JPA? 要解释这个问题,我们先将Spring Data JPA拆成两个部分,即Sping Data和JPA。 从这两个部分来解释。 Spring Data是什么? 摘自: https://spring.io/projects/spring-data Spring Data’s mission is to provide a familiar and cons…...
如何防止CSRF攻击
背景 随着互联网的高速发展,信息安全问题已经成为企业最为关注的焦点之一,而前端又是引发企业安全问题的高危据点。在移动互联网时代,前端人员除了传统的 XSS、CSRF 等安全问题之外,又时常遭遇网络劫持、非法调用 Hybrid API 等新…...
linuxARM裸机学习笔记(7)----RTC实时时钟实验
基础概念: I.MX6U 内部也有个RTC 模块,但是不叫作“ RTC ”,而是叫做“ SNVS ”。 SNVS 直译过来就是安全的非易性存储, SNVS 里面主要是一些低功耗的外设,包括一个 安全的实时计数器 (RTC) 、一个单调计数器 (mo…...
NSS [UUCTF 2022 新生赛]ez_upload
NSS [UUCTF 2022 新生赛]ez_upload 考点:Apache解析漏洞 开题就是标准的上传框 起手式就是传入一个php文件,非常正常的有过滤。 .txt、.user.ini、.txxx都被过滤了,应该是白名单或者黑名单加MIME过滤,只允许.jpg、.png。 猜测二…...
【操作系统】操作系统知识点总结(秋招篇)
文章目录 前言操作系统主要做了哪些工作?进程 线程 协程之间的区别进程的组成部分介绍一下进程的PCB讲一下进程的五态 以及它们的状态转移用户态和内核态是什么?进程在用户态和内核态之间是如何切换的讲一下进程之间的通信方式讲一下进程调度的三个层次介…...
篇十九:迭代器模式:遍历集合
篇十九:"迭代器模式:遍历集合" 开始本篇文章之前先推荐一个好用的学习工具,AIRIght,借助于AI助手工具,学习事半功倍。欢迎访问:http://airight.fun/。 另外有2本不错的关于设计模式的资料&…...
浅谈JVM中的即时编译器(Just-In-Time compiler, JIT)
Java虚拟机(JVM)中的即时编译器(Just-In-Time compiler, JIT)是一个非常重要的组件,它负责将字节码转换为本地机器代码。在不使用JIT的情况下,JVM通过解释字节码来执行程序,这意味着它会为每个字…...
Android 13 Launcher——长按图标弹窗内容修改以及小组件等隐藏起来
目录 一.背景 二.实现思路 三.布局文件修改 四.隐藏代码中原先的view 一.背景 由于定制化开发需要将原先的长按图标原生弹窗界面隐藏,然后显示自定义的弹窗界面,如下就是我们来实现自定义的弹窗界面...
又一个不可错过的编程大模型来了让你惊呼“码农人生”不虚此行
继Stable Diffusion爆火之后,StabilityAI近期又放大招,推出了号称是革命性的编程大模型StableCode。StableCode是其首款用于编码的LLM生成式AI产品,该产品旨在帮助程序员完成日常工作。目前已发布的版本为StableCode-Completion-Alpha-3B&…...
【Express.js】集成SocketIO
集成SocketIO 本节我们介绍在如何在 express 中集成 Socket.IO Socket.IO 算是 WebSocket 的一个超集,进行了一些封装和拓展。 准备工作 创建一个 express.js 项目(本文基于evp-express-cli)安装socket.io.js: npm i socket.io创建代理 …...
为树莓派Pico配置交叉编译环境和工具链arm-none-eabi-gcc时可能会遇到的错误以及解决方案
本文是一个类似手册的文章,用来记录可能遇到的错误。你可以通过侧栏选择遇到的错误来查看详细信息。 No install step for ‘ELF2UF2Build’ 遇到这种错误有两种原因: 安装了版本不对或者不完整的arm-none-eabi-gcc;没有使用正确的 C/C 的…...
Yum 部署K8S集群
目录 1、准备环境 (温馨提示:尽量一次完成集群) 2.安装master节点 3、安装k8s-master上的node 4、安装配置k8s-node1节点 5、安装k8s-node2节点 6、为所有node节点配置flannel网络 7、配置docker开启加载防火墙规则允许转发数据 一. 环…...
初阶C语言-操作符详解(下)
🌞 “等春风得意,等时间嘉许!” 接下来,我们把操作符没学完的继续学完! 操作符详解 6.2sizeof和数组 7.关系操作符8.逻辑操作符9.条件操作符10.逗号表达式11.下标引用、函数调用和结构成员12.表达式求值12.1隐式类型转…...
reposync命令——下载yum仓库中全部的包到本地
reposync命令可以将远端yum仓库里面的包全部都下载到本地。这样构建自己的yum仓库,就不会遇到网络经常更新包而头疼的事情了。 reposync命令在软件包 yum-utils 里面,需要保证yum-utils已安装。 yum install yum-utils -y 常用参数 -r :指定…...
LC-杨辉三角
LC-杨辉三角 链接:https://leetcode.cn/problems/pascals-triangle/submissions/ 上图就是一个杨辉三角,每个数等于他左上角的数与右上角的数之和。 第一行就是一个1;第二行是两个1;第三行的2就是它肩膀上两个1之和,其余的类似。…...
Golang空结构体struct{}的作用是什么?
文章目录 占位符:通道标识:键集合:内存占用优化:总结: 在Go语言中,空结构体 struct{}是一种特殊的数据类型,它不占用任何内存空间。空结构体没有任何字段,也没有任何方法。尽管它看起…...
IDEA运行Tomcat出现乱码问题解决汇总
最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
CSS设置元素的宽度根据其内容自动调整
width: fit-content 是 CSS 中的一个属性值,用于设置元素的宽度根据其内容自动调整,确保宽度刚好容纳内容而不会超出。 效果对比 默认情况(width: auto): 块级元素(如 <div>)会占满父容器…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...
宇树科技,改名了!
提到国内具身智能和机器人领域的代表企业,那宇树科技(Unitree)必须名列其榜。 最近,宇树科技的一项新变动消息在业界引发了不少关注和讨论,即: 宇树向其合作伙伴发布了一封公司名称变更函称,因…...
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分: 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...
论文阅读笔记——Muffin: Testing Deep Learning Libraries via Neural Architecture Fuzzing
Muffin 论文 现有方法 CRADLE 和 LEMON,依赖模型推理阶段输出进行差分测试,但在训练阶段是不可行的,因为训练阶段直到最后才有固定输出,中间过程是不断变化的。API 库覆盖低,因为各个 API 都是在各种具体场景下使用。…...
AD学习(3)
1 PCB封装元素组成及简单的PCB封装创建 封装的组成部分: (1)PCB焊盘:表层的铜 ,top层的铜 (2)管脚序号:用来关联原理图中的管脚的序号,原理图的序号需要和PCB封装一一…...
