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{}是一种特殊的数据类型,它不占用任何内存空间。空结构体没有任何字段,也没有任何方法。尽管它看起…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...
面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...
招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
【JVM】Java虚拟机(二)——垃圾回收
目录 一、如何判断对象可以回收 (一)引用计数法 (二)可达性分析算法 二、垃圾回收算法 (一)标记清除 (二)标记整理 (三)复制 (四ÿ…...
前端中slice和splic的区别
1. slice slice 用于从数组中提取一部分元素,返回一个新的数组。 特点: 不修改原数组:slice 不会改变原数组,而是返回一个新的数组。提取数组的部分:slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...
es6+和css3新增的特性有哪些
一:ECMAScript 新特性(ES6) ES6 (2015) - 革命性更新 1,记住的方法,从一个方法里面用到了哪些技术 1,let /const块级作用域声明2,**默认参数**:函数参数可以设置默认值。3&#x…...
OCR MLLM Evaluation
为什么需要评测体系?——背景与矛盾 能干的事: 看清楚发票、身份证上的字(准确率>90%),速度飞快(眨眼间完成)。干不了的事: 碰到复杂表格(合并单元…...
