xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>❤️ yml 配置
yml
spring:
data:
mongodb:
host: localhost
port: 27017
database: testdb
username: yourUsername
password: yourPassword
authentication-database: admin # 认证数据库,默认是 admin❤️ 实体类
- 类注解
@Document表明文档,指定集合
- 属性注解
@MongoId指定主键 id@Field指定字段在 MongoDB 中的名称
@Version用于实现乐观锁,字段值每次更新时自增,用于并发控制
java
@Document("test_collection")
public class User {
@MongoId
private String id;
@Field("user_name")
private String name;
private int age;
}❤️ 基础 CRUD
💛 MongoRepository
MongoRepository 类似于 JpaRepository
java
public interface UserRepository extends MongoRepository<User, String> {
User findByName(String name);
}💛 MongoTemplate
MongoTemplate 是底层模板类,提供了丰富的 MongoDB 操作方法
保存 :
insert()主键存在就抛异常save主键存在就更新
java
// 不需要给 id 赋值,mongodb 会自动生成主键 id
Employee emp4 = new Employee().setWorkNo("nb004")
.setName("乔豆豆")
.setDepart("财务部")
.setAge(39)
.setMoney(1800);
mongoTemplate.save(emp4);删除 :
java
DeleteResult remove = mongoTemplate.remove(对象);更新 :
java
// 将年龄在 30 岁以下的员工,薪水增加 100 元,部门改为大数据部门
UpdateResult updateResult = mongoTemplate.updateMulti(
Query.query(Criteria.where("age").lt(30)),
new Update().inc("money", 100).set("depart", "大数据部门"),
Employee.class
);查询 :
- 普通查询 / 条件查询
java
// 查询所有员工
List<Employee> list = mongoTemplate.findAll(Employee.class);
// 条件查询:查询研发部,并且年龄大于 30 岁的员工,按照年龄倒序排列
List<Employee> list = mongoTemplate.find(
Query.query(Criteria.where("depart").is("研发部").and("age").gt(30))
.with(Sort.by(Sort.Direction.DESC, "age")),
Employee.class
);- 计数
java
long total = mongoTemplate.count(
Query.query(Criteria.where("money").gt(2000)),
Employee.class
);- 分页查询
java
int page = 2;
int size = 2;
Query query = new Query(criteria)
.skip((page - 1) * size) //跳过多少条
.limit(size) //返回多少条
.with(Sort.by(Sort.Order.asc("money")));
List<Employee> list = mongoTemplate.find(query, Employee.class);❤️ 高阶功能
💛 Criteria 复杂查询条件
- 多条件组合
- 嵌套文档查询
java
{
"name": "Tom",
"address": {
"city": "Tokyo",
"zip": "100-0001"
}
}
List<User> users = mongoTemplate.find(
Query.query(Criteria.where("address.city").is("Tokyo")),
User.class
);java
{
"name": "Alice",
"orders": [
{ "product": "Book", "price": 100 },
{ "product": "Pen", "price": 10 }
]
}
// 流式风格更加推荐
List<User> users = mongoTemplate.query(User.class)
.matching(Query.query(Criteria.where("orders.product").is("Pen")))
.all();- 条件动态拼接
java
List<Criteria> criterias = new ArrayList<>();
// 条件动态拼接
if (age != null) criterias.add(Criteria.where("age").gt(age));
if (name != null) criterias.add(Criteria.where("name").regex(name));
// 将收集到的所有条件组合为 AND 条件
new Criteria().andOperator(criterias.toArray(new Criteria[0]));💛 BasicQuery
BasicQuery 是原生的 json 查询方法,非常复杂,但是功能很丰富
java
BasicQuery query = new BasicQuery("{ age : { $lt : 30 }, name : { $regex : 'l' }}");
List<Person> result = mongoTemplate.find(query, Person.class);💛 聚合查询
- 聚合统计数量
java
// 统计各个部门的人数
AggregationOperation group = Aggregation.group("depart").count().as("empCount");
Aggregation aggregation = Aggregation.newAggregation(group);
AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, Employee.class, Map.class);
for (Map result : results.getMappedResults()) {
System.out.println(result);
}
---
{ "name": "张三", "depart": "研发部" }
{ "name": "李四", "depart": "研发部" }
{ "name": "王五", "depart": "市场部" }
{_id=研发部, empCount=2}
{_id=市场部, empCount=1}- 聚合统计最大值
java
// 统计每个部门,最高的薪水是多少,这里使用的是 max ,当然你也可以使用 min(最小),sum(总和),avg(平均)等方法
AggregationOperation group = Aggregation.group("depart").max("money").as("maxMoney");
Aggregation aggregation = Aggregation.newAggregation(group);
AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, Employee.class, Map.class);
for (Map result : results.getMappedResults()) {
System.out.println(result);
}
---
{ "name": "张三", "depart": "研发部" , "money": 5000 }
{ "name": "李四", "depart": "研发部" , "money": 7000 }
{ "name": "王五", "depart": "市场部" , "money": 6000 }
{_id=开发部, maxMoney=7000}
{_id=市场部, maxMoney=6000}- 聚合随机获取数据
java
// 随机获取 3 个人的信息
TypedAggregation aggregation = Aggregation.newAggregation(Employee.class, Aggregation.sample(3));
AggregationResults<Employee> results = mongoTemplate.aggregate(aggregation, Employee.class);
List<Employee> list = results.getMappedResults();- 有条件地聚合随机获取数据
java
// 随机获取 2 个年龄大于 26 岁的员工
TypedAggregation<Employee> aggregation = TypedAggregation.newAggregation(
Employee.class,
Aggregation.match(Criteria.where("age").gt(26)),
Aggregation.sample(2)
);
List<Employee> list = mongoTemplate.aggregate(aggregation, Employee.class).getMappedResults();💛 动态字段
- 使用 Document 类型,推荐用于字段完全动态的情况
java
Document doc1 = new Document();
doc1.append("name", "Alice");
doc1.append("age", 25);
mongoTemplate.insert(doc1, "my_collection");- 使用 Map
java
Map<String, Object> doc1 = new HashMap<>();
doc1.put("name", "Charlie");
doc1.put("active", true);
mongoTemplate.save(doc1, "my_collection");- 推荐使用动态保留字段,但是不能平铺到顶层
java
@Document("my_collection")
public class MyDynamicEntity {
private String name;
private Integer age;
private Map<String, Object> properties;
}
{
"name": "Alice",
"age": 25,
"properties": {
"customField1": "value1",
"customField2": 123
}
}❤️ 其他
https://cloud.tencent.com/developer/article/2441738
https://www.hxstrive.com/subject/spring_data_mongodb/1980.htm