MongoDB经典入门系列
在项目中我们更多的是使用Spring整合MongoDB进行开发,直接面向对象操作MongoDB的API即可,这里使用spring-boot-starter-data-mongodb
集成Mongodb
第一步:创建项目导入基础依赖,SpringBoot和Mongodb
<parent>
<groupId> org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
第二步:创建启动类
@SpringBootApplication
public class MongoDemoApplication {
public static void main(String[] args) {
SpringApplication.run(MongoDemoApplication.class, args);
}
}
第三步:yml配置mongodb
spring:
data:
mongodb:
uri: mongodb://testuser:testuser@127.0.0.1:27017/tempdb?authSource=admin&authMechanism=SCRAM-SHA-1
第四步:编写实体类,SpringData提供了@Document注解来标记文档对象 ,如下
@Document(collection = "students") //集合名字
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
@Id //对应id , 字段名对应了mongo中的——id
private String _id;
//标记字段再mongo中的名字和类型
@Field(name = "name",targetType = FieldType.STRING)
private String name;
@Field(name = "age" , targetType = FieldType.INT32)
private Integer age;
@Field(name = "sex" , targetType = FieldType.INT32)
private Integer sex;
private Teacher teacher;
}
第五步:编写repository接口,SpringData提供了MongoRepository接口,其中提供了基础的CRUD方法
@Repository
public interface TeacherMongoRepository extends MongoRepository<Student,String> {
}
解释:这里的泛型是标记了@Document的实体类,和id的类型
MongDB的CRUD
在SpringData中我们可以注入:MongoTemplate实现CRUD, 也可以使用刚才创建的 repository 。
实例:保存文档到Mongdb
@RunWith(SpringRunner.class)
@SpringBootTest(classes = MongoDemoApplication.class)
class MongoDemoApplicationTests {
@Autowired
private MongoTemplate mongoTemplate;
@Autowired
private StudentMongoRepository repository;
@Test
public void saveTest() {
List<Student> students = new ArrayList<>(50);
for (int i = 0; i < 100; i++){
Student student = new Student(i+"", i%2==0?"zs":"ls", i, i%3==0?1:0, null);
students.add(student);
}
//mongoTemplate.insert(student);
//mongoTemplate.save()
//如果ID存在就会变成修改
repository.saveAll(students);
//不允许ID重复
//repository.insert(students);
}
}
实例:修改文档 , 可以使用repository.save或mongoTemplate.save方法修改,也可以使用mongoTemplate.updateFirst
@Test
public void updateTest() {
//条件
Query query = Query.query(Criteria.where("name").is("zs"));
//修改的内容
Update update = new Update().set("age", 18);
//执行修改
UpdateResult result = mongoTemplate.updateFirst(query, update, "students");
//UpdateResult result = mongoTemplate.updateMulti(query, update, "students");
System.out.println(result);
}
实例:根据ID删除 ,或根据条件删除
- Query.query : 构建删除查询对象
- Criteria.where : 构建具体条件
@Test
public void deleteTest() {
//repository.deleteById("2");
//根据条件删除,把name=zs的从students这个集合中删除掉
Query query = Query.query(Criteria.where("name").is("zs"));
DeleteResult result = mongoTemplate.remove(query, "students");
System.out.println(result);
}
实例:根据ID查找 ,或查找所有
@Test
public void findTest() {
Student findResult = repository.findById("2").get();
System.out.println(findResult);
//查找所有
repository.findAll().forEach(student -> System.out.println(student));
}
实例:复杂查找
- 使用 Query.query 构建query
- 使用Criteria.where构建具体条件
- query.with添加分页和排序
- mongoTemplate.count查询条数
- mongoTemplate.find 查找列表
@Test
public void searchTest() {
//repository.findAll().forEach(student -> System.out.println(student));
//带条件查询,组合多个条件 ,带分页
Query query = Query.query(Criteria.where("sex").is(1));
//范围查询
query.addCriteria(Criteria.where("age").gte(18));
//正则查询
query.addCriteria(Criteria.where("name").regex("zs"));
//包含查询
//query.addCriteria(Criteria.where("age").in(18,19));
//and条件并列
Criteria criteria = Criteria.where("字段").is("值")
.andOperator(Criteria.where("字段").is("值"), Criteria.where("字段").is("值"));
//or 条件
criteria = Criteria.where("字段").is("值")
.orOperator(Criteria.where("字段").is("值"), Criteria.where("字段").is("值"));
//取反
criteria = Criteria.where("字段").is("值")
.norOperator(Criteria.where("字段").is("值"), Criteria.where("字段").is("值"));
//query.addCriteria(criteria);
//查询条数
long total = mongoTemplate.count(query, "students");
System.out.println("总条数 = "+total);
//分页翱翔
//query.skip(跳过条数).limit(每页条数);
//第3页 0开始, 每页10条
query.with(PageRequest.of(0,10));
//按照age倒排
query.with(Sort.by(Sort.Order.desc("age")));
//查询列表
List<Student> students = mongoTemplate.find(query, Student.class);
students.forEach(student -> System.out.println(student));
}
聚合查询
- 使用 mongoTemplate.aggregate 做聚合查询
- 使用 Aggregation.match 构建匹配条件
- Aggregation.group("name") 构建分组
@Test
public void testAgg(){
//构建匹配条件
MatchOperation matchOperation = Aggregation.match(Criteria.where("age").gt(50));
//构建分组条件,按照age分组,统计条数
GroupOperation groupOperation = Aggregation.group("name")
//统计age总和
.sum("age").as("totalAge")
//统计条数
.count().as("nums");
//创建一个agg对象
Aggregation aggregation = TypedAggregation.newAggregation(matchOperation,groupOperation);
//执行聚合查询,一map返回结果
AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, "students", Map.class);
Iterator<Map> iterator = results.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
//{_id=ls, totalAge=1875, nums=25}
//{_id=zs, totalAge=1800, nums=24}
}