MySQL 适合结构化数据,Redis 适合缓存,而 MongoDB 则是介于两者之间------它是一款文档型 NoSQL 数据库 ,以类似 JSON 的 BSON 格式存储数据,结构灵活、无需预定义表结构、支持复杂查询、横向扩展方便,非常适合存储非结构化/半结构化数据。
一、MongoDB 适用场景
-
• 文章、博客、评论、日志类数据(字段多变)
-
• 用户画像、行为数据、埋点上报
-
• 配置中心、动态表单、商品详情
-
• 大数据量、高写入、低事务要求的业务
-
• 需要频繁扩展字段,不想频繁改表结构
二、环境准备
-
• 安装并启动 MongoDB(本地或云服务)
-
• SpringBoot 2.x / 3.x
-
• MongoDB 客户端工具(Navicat、Mongo Compass 等)
三、引入核心依赖
go
<!-- SpringBoot MongoDB 启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
四、application.yml 配置
go
spring:
data:
mongodb:
# 无密码形式
uri: mongodb://localhost:27017/mongo_demo
# 有密码(账号密码+认证库)
# uri: mongodb://root:123456@localhost:27017/mongo_demo?authSource=admin
-
•
mongo_demo是数据库名,不存在会自动创建 -
• 无需手动建库建集合(collection),插入数据自动生成
五、MongoDB 常用注解
-
•
@Document:标记为 MongoDB 文档实体,对应集合 -
•
@Id:主键,默认生成_id -
•
@Field("field_name"):指定数据库字段名 -
•
@Transient:不存入数据库 -
•
@Indexed:创建索引,提升查询速度 -
•
@CompoundIndex:复合索引
六、实体类编写
以文章(Article)为例:
go
package com.demo.entity;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;
import java.time.LocalDateTime;
import java.util.List;
@Data
@Document(collection = "article") // 指定集合名称
public class Article {
@Id
private String id;
@Indexed // 为标题创建索引
private String title;
private String content;
@Field("author_name")
private String authorName;
private Integer viewCount;
private List<String> tags;
private LocalDateTime createTime;
private LocalDateTime updateTime;
}
七、两种操作方式
SpringBoot 提供两种操作 MongoDB 的方式:
-
- MongoRepository:简单 CRUD,类似 JPA
-
- MongoTemplate:灵活复杂查询、聚合、更新,生产更常用
方式一:MongoRepository 快速 CRUD
1. 编写 Repository 接口
go
package com.demo.repository;
import com.demo.entity.Article;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface ArticleRepository extends MongoRepository<Article, String> {
// 按作者名查询
List<Article> findByAuthorName(String authorName);
// 按标题模糊查询
List<Article> findByTitleLike(String title);
}
2. 基础 CRUD 示例
go
@Service
@RequiredArgsConstructor
public class ArticleService {
private final ArticleRepository repository;
// 新增/修改
public Article save(Article article) {
article.setCreateTime(LocalDateTime.now());
return repository.save(article);
}
// 根据ID查询
public Article findById(String id) {
return repository.findById(id).orElse(null);
}
// 查询所有
public List<Article> findAll() {
return repository.findAll();
}
// 删除
public void deleteById(String id) {
repository.deleteById(id);
}
// 按作者查询
public List<Article> findByAuthor(String authorName) {
return repository.findByAuthorName(authorName);
}
}
方式二:MongoTemplate 复杂查询
企业开发绝大多数场景使用 MongoTemplate,灵活、强大。
1. 通用条件查询
go
@Autowired
private MongoTemplate mongoTemplate;
// 条件构造器
Query query = new Query();
// 精确匹配
query.addCriteria(Criteria.where("authorName").is("张三"));
// 大于
query.addCriteria(Criteria.where("viewCount").gt(100));
// 模糊查询(包含)
query.addCriteria(Criteria.where("title").regex("Java"));
// 且条件
query.addCriteria(Criteria.where("authorName").is("张三").and("viewCount").gt(100));
// 或条件
query.addCriteria(new Criteria().orOperator(
Criteria.where("authorName").is("张三"),
Criteria.where("viewCount").gt(1000)
));
// 查询列表
List<Article> list = mongoTemplate.find(query, Article.class);
2. 分页查询
go
// 页码从0开始
Pageable pageable = PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC, "createTime"));
Query pageQuery = new Query().with(pageable);
List<Article> pageList = mongoTemplate.find(pageQuery, Article.class);
// 总条数
long total = mongoTemplate.count(pageQuery, Article.class);
3. 字段更新
go
// 更新浏览量 +1
Query query = Query.query(Criteria.where("_id").is(id));
Update update = new Update().inc("viewCount", 1);
mongoTemplate.updateFirst(query, update, Article.class);
4. 批量更新
go
mongoTemplate.updateMulti(query, update, Article.class);
5. 聚合查询(统计、分组)
go
// 按作者分组统计文章数量
Aggregation aggregation = Aggregation.newAggregation(
Aggregation.group("authorName").count().as("count"),
Aggregation.sort(Sort.by(Sort.Direction.DESC, "count"))
);
AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, "article", Map.class);
List<Map> mapList = results.getMappedResults();
八、MongoDB 索引
为高频查询字段加索引,性能提升巨大:
go
// 单字段索引
@Indexed
// 唯一索引
@Indexed(unique = true)
// 复合索引
@CompoundIndex(def = "{'authorName':1, 'createTime':-1}")
创建后可在 MongoDB 中查看:
go
db.article.getIndexes()
九、MongoDB vs MySQL 简单对比
-
• MySQL:表结构固定、事务强、适合强一致性业务
-
• MongoDB:结构灵活、无表结构约束、查询快、适合海量半结构化数据
十、注意事项
-
- 无事务默认不保证原子性,高并发需加锁或使用事务
-
- 索引不能乱建,过多索引影响写入性能
-
- 超大文档(>16MB)不适合直接存储,可存文件服务地址
-
- 模糊查询
regex不命中索引,尽量前缀匹配
- 模糊查询
-
- 分页深度翻页性能差,建议用游标分页
十一、总结
SpringBoot 整合 MongoDB 非常简单:
引依赖 → 配连接 → 写实体 → 用 MongoTemplate / Repository
它结构灵活、开发极快,特别适合文章、评论、日志、用户行为等场景。掌握 CRUD、条件查询、分页、更新、索引,基本能覆盖 90% 的业务开发。
你在项目中用过 MongoDB 吗?一般用来存什么业务数据?有没有遇到什么坑?
欢迎在评论区留言交流,关注我,持续更新 SpringBoot 全栈实战教程。