当前位置: 首页 > news >正文

MongoDB基本使用(包含工具类)

示例代码

zr/MongoDemo

✅ 1. MongoDB 概述

🔷1.1 MongoDB 是什么?

  • 文档数据库(Document DB)
  • 数据以 BSON 格式存储(类似 JSON)
  • 每条数据叫 document
  • 多条 document 存储在 collection
  • 多个 collection 组成 database

🔷1.2 与 MySQL 的对比

MySQLMongoDB
关系型表结构无固定 schema
强类型弱结构,字段可变
JOIN 多无 JOIN,需要聚合
行式存储文档存储(嵌套结构)
适合强一致适合灵活可扩展场景

🔷1.3 文档示例

{"_id": "123","name": "eric","tags": ["dev", "java"],"address": {"city": "shanghai","code": 200000}
}

✅ 2. Docker 启动 MongoDB

🔷2.1 拉取镜像

docker pull mongo:7.0

🔷2.2 启动单节点 MongoDB(开发环境)

docker run -d \--name mongodb \-p 27017:27017 \-e MONGO_INITDB_ROOT_USERNAME=admin \-e MONGO_INITDB_ROOT_PASSWORD=123456 \mongo:7.0

🔷2.3 使用图形化界面(强烈推荐)

✅ 方案 1:直接下载安装(最推荐,官方方式)

官网下载:
https://www.mongodb.com/products/tools/compass

✅ 方案 2:当然,用navicat连接也是可以(个人推荐)


✅ 3. Spring Boot 使用 MongoDB

🔷3.1 添加依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><scope>provided</scope>
</dependency>
<dependency><groupId>com.alibaba.fastjson2</groupId><artifactId>fastjson2</artifactId><version>2.0.59</version>
</dependency>

🔷3.2 配置 application.yml

spring:data:mongodb:uri: mongodb://admin:123456@localhost:27017/test?authSource=admin

🔷3.3 创建实体

@Data
@Document("user")
public class User {@Idprivate String id;private String name;private int age;
}

🔥3.4 对mongo进行操作

🔹3.4.1 对比

MongoRepository = 简单 CRUD 自动化,像 JPA
MongoTemplate = 灵活强大、复杂查询必用,像 MyBatis

特性MongoRepositoryMongoTemplate
编程风格声明式(接口)命令式(代码)
上手难度极低较高
CRUD 能力简单 CRUD 自动生成CRUD 全手写
复杂查询能力弱(QueryDSL 才稍强)能力最强(支持聚合、管道等)
聚合操作(Aggregation)不支持✅ 支持
多条件动态查询不方便✅ 最适合
分页排序简单支持✅ 全支持
事务控制支持支持
适合场景普通 CRUD、快速开发高级查询、复杂条件、聚合分析
🔹3.4.1 Repository 使用方式(最简单)
  1. 继承MongoRepository
  public interface UserRepository extends MongoRepository<User, String> {List<User> findByName(String name);}
  1. 编写UserService
package com.zr.mongodemo.service;import com.zr.mongodemo.entity.User;
import com.zr.mongodemo.repository.UserRepository;
import org.springframework.stereotype.Service;import java.util.List;/*** @Author: zr* @Date: 2025/11/03/13:59* @Description:*/
@Service
public class UserService {private final UserRepository repo;public UserService(UserRepository repo) {this.repo = repo;}public User create(User user) {return repo.save(user);}public User get(String id) {return repo.findById(id).orElse(null);}public List<User> list() {return repo.findAll();}public User update(User user) {return repo.save(user);   // save = insert or update}public void delete(String id) {repo.deleteById(id);}
}
  1. 编写测试类
package com.zr.mongodemo;import com.alibaba.fastjson2.JSON;
import com.zr.mongodemo.entity.User;
import com.zr.mongodemo.repository.UserRepository;
import com.zr.mongodemo.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.util.List;@SpringBootTest
@Slf4j
class MongoDemoApplicationTests {@Autowiredprivate UserService userService;@Testvoid create() {User user = new User();user.setId("2");user.setName("zr2");user.setAge(19);userService.create(user);}@Testvoid list() {List<User> list = userService.list();log.info("list: {}", JSON.toJSONString(list));}@Testvoid get() {User user = userService.get("1");log.info("user: {}", JSON.toJSONString(user));}@Testvoid update() {User user = new User();user.setId("1");user.setAge(20);userService.update(user);}@Testvoid delete() {userService.delete("1");}}

3.1 测试新增

可以看到新增了一条数据

3.2 测试列表查询

可以看到返回了多条数据

3.3 测试id获取

可以看到返回了对应id的数据

3.4 测试更新

此处发现一个问题,没有设置的字段会被清空

3.4.1 只更新不为空的字段

回滚数据

创建MongoUpdateUtil使用反射的方式,只对每个非空字段做赋值处理

package com.zr.mongodemo.util;import org.springframework.data.mongodb.core.query.Update;import java.lang.reflect.Field;/*** @Author: zr* @Date: 2025/11/03/14:44* @Description:*/
public class MongoUpdateUtil {public static Update convertToUpdate(Object obj) {Update update = new Update();Field[] fields = obj.getClass().getDeclaredFields();for (Field field : fields) {field.setAccessible(true);try {Object value = field.get(obj);// 跳过 id,跳过 nullif (value != null && !"id".equals(field.getName())) {update.set(field.getName(), value);}} catch (IllegalAccessException e) {throw new RuntimeException(e);}}return update;}
}

此处还是用到了mongoTemplate

    public void update2(User user) {Query query = Query.query(Criteria.where("_id").is(user.getId()));Update update = MongoUpdateUtil.convertToUpdate(user);mongoTemplate.updateFirst(query, update, User.class);}

修改id为1的年龄为20

可以看到没有更新的字段没有被清空,需要更新的字段也更新了

3.5 删除

可以看到对应数据被删除了

🔹3.4.2 Template 使用方式(更灵活)
@Autowired
MongoTemplate mongoTemplate;public User save(User user) {
return mongoTemplate.save(user);
}

工具类对mongo进行操作

package com.zr.mongodemo.util;import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;import org.springframework.data.mongodb.core.query.Update;import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;/*** @Author: zr* @Date: 2025/11/03/15:06* @Description:*/
public class MongoTemplateUtil {private final MongoTemplate mongoTemplate;public MongoTemplateUtil(MongoTemplate mongoTemplate) {this.mongoTemplate = mongoTemplate;}// ✅ 插入public <T> T insert(T obj) {return mongoTemplate.insert(obj);}// ✅ 根据 ID 查询public <T> T findById(String id, Class<T> clazz) {return mongoTemplate.findById(id, clazz);}// ✅ 查询所有public <T> List<T> findAll(Class<T> clazz) {return mongoTemplate.findAll(clazz);}// ✅ 单字段查询public <T> List<T> findByField(String field, Object value, Class<T> clazz) {Query query = Query.query(Criteria.where(field).is(value));return mongoTemplate.find(query, clazz);}// ✅ 多条件精确查询public <T> List<T> findByFields(Map<String, Object> map, Class<T> clazz) {Query query = new Query();map.forEach((k, v) -> query.addCriteria(Criteria.where(k).is(v)));return mongoTemplate.find(query, clazz);}// ✅ 分页查询 + 排序public <T> List<T> findPage(Query query, int page, int size, String sortField, boolean asc, Class<T> clazz) {if (sortField != null) {query.with(Sort.by(asc ? Sort.Direction.ASC : Sort.Direction.DESC, sortField));}query.skip((long) (page - 1) * size);query.limit(size);return mongoTemplate.find(query, clazz);}// ✅ 获取数量public long count(Query query, Class<?> clazz) {return mongoTemplate.count(query, clazz);}// ✅ 删除public void deleteById(String id, Class<?> clazz) {Query query = Query.query(Criteria.where("_id").is(id));mongoTemplate.remove(query, clazz);}// ✅ 按条件批量删除public void deleteByFields(Map<String, Object> map, Class<?> clazz) {Query query = new Query();map.forEach((k, v) -> query.addCriteria(new Criteria(k).is(v)));mongoTemplate.remove(query, clazz);}// ✅ ✅ 动态局部更新(自动忽略 null 字段)public <T> void updatePartialById(T obj) {try {Field idField = obj.getClass().getDeclaredField("id");idField.setAccessible(true);Object idValue = idField.get(obj);if (idValue == null) {throw new RuntimeException("id 不能为空");}Query query = Query.query(Criteria.where("_id").is(idValue));Update update = buildDynamicUpdate(obj);mongoTemplate.updateFirst(query, update, obj.getClass());} catch (Exception e) {throw new RuntimeException(e);}}// ✅ 核心:构建动态 Update,只更新非 null 字段private <T> Update buildDynamicUpdate(T obj) {Update update = new Update();Field[] fields = obj.getClass().getDeclaredFields();for (Field f : fields) {f.setAccessible(true);try {Object value = f.get(obj);String fieldName = f.getName();if ("id".equals(fieldName) || value == null) {continue;}update.set(fieldName, value);} catch (Exception e) {throw new RuntimeException(e);}}return update;}// ✅ 条件更新(多条件 WHERE)public <T> void updatePartialByQuery(Query query, T obj, Class<T> clazz) {Update update = buildDynamicUpdate(obj);mongoTemplate.updateMulti(query, update, clazz);}
}

该工具类支持的能力

功能方法
新增insert(obj)
根据 ID 查询findById(id)
全查询findAll()
单字段查询findByField()
多字段查询findByFields()
分页findPage()
获取数量count()
删除 IDdeleteById()
条件批量删除deleteByFields()
✅ 动态局部更新(自动忽略 null)updatePartialById()
✅ 条件更新updatePartialByQuery()

使用示例

package com.zr.mongodemo.service;import com.zr.mongodemo.entity.User;
import com.zr.mongodemo.repository.UserRepository;
import com.zr.mongodemo.util.MongoTemplateUtil;
import com.zr.mongodemo.util.MongoUpdateUtil;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;import java.util.List;/*** @Author: zr* @Date: 2025/11/03/13:59* @Description:*/
@Service
public class UserServiceTemplate {private final MongoTemplateUtil mongoUtils;@Autowiredpublic UserServiceTemplate(MongoTemplate mongoTemplate) {this.mongoUtils = new MongoTemplateUtil(mongoTemplate);}public void add(User user) {mongoUtils.insert(user);}public User get(String id) {return mongoUtils.findById(id, User.class);}public void update(User user) {mongoUtils.updatePartialById(user); // ✅ 动态局部更新}public void delete(String id) {mongoUtils.deleteById(id, User.class);}public List<User> list() {return mongoUtils.findAll(User.class);}
}

✅ 4. 高级用法(非常实用)

🔶4.1 建索引

@Document("user")
public class User {@Indexedprivate String name;
}

🔶4.2 聚合查询(类似 SQL group by)

Aggregation agg = Aggregation.newAggregation(Aggregation.group("age").count().as("count")
);List<Document> result = mongoTemplate.aggregate(agg, "user", Document.class).getMappedResults();

🔶4.3 分页查询

Query query = new Query().limit(10).skip(20);
List<User> list = mongoTemplate.find(query, User.class);

✅ 5. Docker Compose 部署 MongoDB 副本集(生产环境)

当你需要:
✔ 数据高可用
✔ 支持事务
✔ 副本集复制

使用下面配置:

🔶docker-compose.yml

version: "3"
services:mongo1:image: mongo:7.0container_name: mongo1ports:- "27017:27017"environment:- MONGO_INITDB_ROOT_USERNAME=admin- MONGO_INITDB_ROOT_PASSWORD=123456- TZ=Asia/Shanghaicommand: ["--replSet", "rs0"]mongo2:image: mongo:7.0container_name: mongo2environment:- MONGO_INITDB_ROOT_USERNAME=admin- MONGO_INITDB_ROOT_PASSWORD=123456command: ["--replSet", "rs0"]mongo3:image: mongo:7.0container_name: mongo3environment:- MONGO_INITDB_ROOT_USERNAME=admin- MONGO_INITDB_ROOT_PASSWORD=123456command: ["--replSet", "rs0"]

✅ 6. 常见错误与解决方案

❗ Invalid BSON field name

出现:

Invalid BSON field name

原因:
✅ MongoDB key 不能包含以下字符:

  • "."
  • "$"

比如错误例子:

{"status.pass": "ok"  // 错误
}

解决方式:

  • 替换 “.” → “_”
  • 使用 @Field 映射
  • 复杂结构用 Document 包装

http://www.dtcms.com/a/566309.html

相关文章:

  • 和15岁女儿做很舒服网站网页设计软件排名
  • 高防IP真能100%防御DDoS攻击吗
  • 新建网站怎么做优化广州建设工程交易中心改版
  • 申请免费网站公司长春网站建设哪家好
  • SQL SERVER 索引
  • 深入浅出 Java 虚拟机之基础原理
  • 【数维杯赛中助攻+1,英文普刊知网检索+1】
  • 发布 php 微网站网站建设销售提成
  • 哈尔滨网站建设赚钱么自己做的视频网站上传电影
  • 建设电子商务网站前的市场分析合肥有哪些做网站的公司
  • 免费cms建站微网站开发平台 知乎
  • css学习盒模型:
  • 杭州网站建设出 名wordpress生成静态 mip
  • js 实现深拷贝
  • 素材设计做的好的网站有哪些帝国 网站搬家
  • 商城手机网站设计做阿里巴巴网站图片尺寸
  • 小说网站seo排名怎么做自己做个网站需要什么
  • 计算机网络R2025秋(TYUT)【计算机网络】第5章 运输层
  • 广州站八个字网站中新颖的功能
  • 梳理了音视频开发核心知识点
  • dedecms怎么把一个网站的文章导出导到另一个站里中国工程建设交易信息网站
  • 计算机网络8
  • 霍山有没有做建网站的商洛市城乡建设规划局网站
  • 厦门seo网站管理网站建设好后怎样形成app
  • Vue 生成 PDF 完整教程
  • 【C++日志库】启程者团队开源:轻量级高性能VoyLog日志库完全指南
  • 【Dify】详细介绍+功能说明
  • 做a手机视频在线观看网站3d装修效果图制作软件
  • 从化营销网站建设高新区微网站建设
  • 【区间贪心 区间覆盖】1326. 灌溉花园的最少水龙头数目|1885