SpringBoot整合MongoDB全过程

 更新时间:2024年05月29日 10:21:00   作者:一只咸鱼。。  
这篇文章主要介绍了SpringBoot整合MongoDB全过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

一、环境准备

①添加 SpringData 依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

②配置 yml 文件,官方连接配置文档

方式一:

spring:
  data:
    mongodb:
      uri: mongodb://root:123456@1.15.76.95:27017/library?authSource=admin

方式二:

spring:
  data:
    mongodb:
      username: root
      password: 123456
      host: 1.15.76.95
      port: 27017
      database: library
      authentication-database: admin

③直接注入 MongoTemplate 进行操作

@Resource
MongoTemplate mongoTemplate;

二、集合操作

@Test
public void testCollection(){
	boolean exists = mongoTemplate.collectionExists("borrow");
	if(exists) {
		// 删除集合
		mongoTemplate.dropCollection("borrow");
	}else {
		// 创建集合
		mongoTemplate.createCollection("borrow");
	}
	Set<String> collectionNames = mongoTemplate.getCollectionNames();
    System.out.println(collectionNames.toString());  // [borrow, book, user]
}

三、文档操作

3.1 实体类

@Document

  • 修饰范围:用在类上。
  • 作用:用来映射这个类的一个对象为 Mongo 中一条文档数据。
  • 属性:(value 、collection) 用来指定操作的集合名称。

@MongoId

  • 修饰范围:用在成员变量、方法上。
  • 作用:用来将成员变量的值映射为文档的 _id 的值。

@Field

  • 修饰范围:用在成员变量、方法上。
  • 作用:用来将成员变量及其值映射为文档中一个 key:value 对。
  • 属性:(name , value) 用来指定在文档中 key 的名称,默认为成员变量名。

@Transient

  • 修饰范围:用在成员变量、方法上。
  • 作用:用来指定此成员变量不参与文档的序列化。
@Data
@AllArgsConstructor
@NoArgsConstructor
@Document("user")
public class User {
    @MongoId
    private Integer uid;
    @Field
    private String name;
    @Field
    private String password;
    @Field
    private Integer age;
}

3.2 添加文档

insert 方法返回值是新增的 Document 对象,里面包含了新增后 id 的值。

如果集合不存在会自动创建集合。

@Test
public void test1() {
    // _id存在时更新数据
    mongoTemplate.save(new User(1, "aaa", "123456", 20));
    // _id存在时抛出异常
    mongoTemplate.insert(new User(2, "bbb", "113456", 21));

    List<User> list = Arrays.asList(
            new User(3, "ccc", "124266", 22),
            new User(4, "ddd", "136521", 23),
            new User(5, "eee", "147258", 24));
    // 批量插入
    mongoTemplate.insert(list, User.class);
}

通过 Spring Data MongoDB 还会给集合中多加一个 _class 的属性,存储新增时 Document 对应 Java 中类的全限定路径。

这么做为了查询时能把 Document 转换为 Java 类型。


3.3 查询文档

  • Query 类作为查询条件的容器,用于放置 Criteria 条件接口。
  • Criteria 是标准查询的接口,可以引用静态的
  • Criteria.where() 将字段和条件组合在一起进行查询。
@Test
public void test1() {
	System.out.println("==========查询所有文档===========");
    List<User> list = mongoTemplate.findAll(User.class);
    list.forEach(System.out::println);

    System.out.println("==========根据_id查询===========");
    User user = mongoTemplate.findById(3, User.class);
    System.out.println(user);

    System.out.println("==========findOne返回第一个文档===========");
    User one = mongoTemplate.findOne(new Query(), User.class);
    System.out.println(one);
}
@Test
public void test2() {
	System.out.println("==========条件查询===========");
	// 查询name为"eee"的用户
	Query query1 = new Query(Criteria.where("name").is("eee"));
	// 查询 age<23 的用户
	Query query2 = new Query(Criteria.where("age").lt(23));
	// 查询 21<=age<24 的用户
	Query query3 = new Query(Criteria.where("age").gte(21).lt(24));
	// 模糊查询
	Query query4 = new Query(Criteria.where("password").regex("123"));

	System.out.println("==========多条件查询===========");
	// 查询 age<24 且 密码包含"123" 的用户
	Criteria criteria1 = new Criteria();
	criteria1.andOperator(Criteria.where("age").lt(24), Criteria.where("password").regex("123"));
	Query query5 = new Query(criteria1);
	// 查询 age>23 或 密码包含"456" 的用户
	Criteria criteria2 = new Criteria();
	criteria2.orOperator(Criteria.where("age").gt(23), Criteria.where("password").regex("456"));
	Query query6 = new Query(criteria2);

	List<User> list = mongoTemplate.find(query6, User.class);
	list.forEach(System.out::println);
}
@Test
public void test3() {
	System.out.println("==========排序===========");
	Query query1 = new Query();
	query1.with(Sort.by(Sort.Order.desc("age")));

	System.out.println("==========分页===========");
	Query query2 = new Query();
	query2.skip(0).limit(3);

	List<User> list = mongoTemplate.find(query2, User.class);
	list.forEach(System.out::println);
}

使用 JSON 字符串方式查询:

@Test
public void testFindByJson() {
	// 等值查询
	Query query1 = new BasicQuery("{name:'eee'}");
	// 多条件查询
	Query query2 = new BasicQuery("{age:{$lt:24}, password:{$regex:'123'}}");
	Query query3 = new BasicQuery("{$or:[{age:{$gt:23}}, {password:{$regex:'456'}}]}");

	List<User> list = mongoTemplate.find(query3, User.class);
	list.forEach(System.out::println);
}

3.4 修改文档

在 Mongodb 中无论是使用客户端 API 还是使用 Spring Data,更新返回结果一定是受行数影响。如果更新后的结果和更新前的结果是相同,返回 0。

  • updateFirst():只更新满足条件的第一条记录。
  • updateMulti():更新所有满足条件的记录。
  • upsert():没有符合条件的记录则插入数据。
@Test
public void test1() {
	Query query = new Query(Criteria.where("name").is("eee"));
	Update update = new Update();
	update.set("age", 25);
	// updateFirst() 只更新满足条件的第一条记录
	UpdateResult updateResult = mongoTemplate.updateFirst(query, update, User.class);
	System.out.println("返回修改的记录数: " + updateResult.getModifiedCount());
}
@Test
public void test2() {
	Query query = new Query(Criteria.where("age").gt(23));
	Update update = new Update();
	update.inc("age", 1);
	// updateMulti() 更新所有满足条件的记录
    UpdateResult updateResult = mongoTemplate.updateMulti(query, update, User.class);
	System.out.println("返回修改的记录数: " + updateResult.getModifiedCount());
}
@Test
public void test3() {
	// query查询结果不存在
	Query query = new Query(Criteria.where("name").is("ggg"));
	Update update = new Update();
	update.set("age", 28);
	update.setOnInsert("_id", 7); //不存在时插入
	// upsert() 没有符合条件的记录则插入数据
	UpdateResult updateResult = mongoTemplate.upsert(query, update, User.class);
	System.out.println("返回修改的记录数: " + updateResult.getModifiedCount());
}

3.5 删除文档

@Test
public void testDelete() {
	//删除所有文档, 不如用dropCollection()
	//mongoTemplate.remove(new Query(),Employee.class);
        
	//条件删除
	Query query = new Query(Criteria.where("name").is("fff"));
	mongoTemplate.remove(query, User.class);
}

四、聚合操作

4.1 使用 Aggregation 实现

用 Aggregation 集合接收聚合操作,用 MongoTemplate 对象直接调用 aggregate,传入聚合操作集合、表名、映射对象。

@Test
public void testAggregation() {
	// 1.先定义聚合操作
	MatchOperation match = Aggregation.match(Criteria.where("type").is("novel"));
	SortOperation sort = Aggregation.sort(Sort.Direction.ASC, "favCount");
	// 2.按顺序组合每一个聚合步骤
	TypedAggregation<Book2> typedAggregation = Aggregation.newAggregation(Book2.class, match, sort);
	// 3.执行聚合操作, 可以使用 Document、Map、自定义实体类 接收结果
	AggregationResults<Document> aggregate = mongoTemplate.aggregate(typedAggregation, Document.class);
	List<Document> results = aggregate.getMappedResults();
	results.forEach(System.out::println);
}

4.2 使用 Aggregates 实现

用 Aggregates 和 Bson 构建聚合操作对象,用预先生成的 MongoCollection 对象调用 aggregate 执行。

@Test
public void testAggregates(){
	// 1.先通过集合名拿到所有文档
	MongoCollection<Document> collection = mongoTemplate.getCollection("book2");
	
	// 2.Aggregates提供各种聚合操作符,返回一个Bson对象
	Bson matchBson = Aggregates.match(new Document("type", "travel"));
//	Bson matchBson = Aggregates.match(Filters.eq("type", "travel"));//Filters来实现过滤
	Bson sortBson = Aggregates.sort(Sorts.ascending("favCount"));
//	Bson sortBson = Aggregates.sort(new Document("favCount", 1));
	
	// 3.构建一个List<Bson>, 并把每一个聚合操作按顺序加进去
	List<Bson> bsonList = new ArrayList<>();
	bsonList.add(matchBson);
	bsonList.add(sortBson);
	
	// 4.最后传入aggregate方法中执行,并且接收结果集
	AggregateIterable<Document> resultList = collection.aggregate(bsonList);
	resultList.forEach(System.out::println);
}

示例一:统计文档中的书籍总量、收藏总数、平均收藏量

@Test
public void test1() {
    MongoCollection<Document> collection = mongoTemplate.getCollection("book2");

    Bson groupBson = Aggregates.group(null,
            Accumulators.sum("bookCount", 1),
            Accumulators.sum("favCount", "$favCount"),
            Accumulators.avg("favAvg", "$favCount"));

    List<Bson> bsonList = new ArrayList<>();
    bsonList.add(groupBson);

    AggregateIterable<Document> resultList = collection.aggregate(bsonList);
    resultList.forEach(System.out::println);
}

示例二:统计tag标签的热度排行 (根据favCount总量排行即为热度)

@Test
public void test4() {
    MongoCollection<Document> collection = mongoTemplate.getCollection("book2");

    Bson unwindBson = Aggregates.unwind("$tag");
    Bson groupBson = Aggregates.group("$tag", Accumulators.sum("favCount", "$favCount"));
    Bson sortBson = Aggregates.sort(new Document("favCount", -1));

    List<Bson> bsonList = new ArrayList<>();
    bsonList.add(unwindBson);
    bsonList.add(groupBson);
    bsonList.add(sortBson);

    AggregateIterable<Document> resultList = collection.aggregate(bsonList);
    resultList.forEach(System.out::println);
}

4.3 应用案例

示例一:统计每个作者的每本book的收藏数

@Test
public void test1() {
    GroupOperation group = Aggregation
            .group("$author.name", "$title")
            .sum("$favCount").as("favCount");
    TypedAggregation<Book2> typedAggregation = Aggregation.newAggregation(Book2.class, group);
    AggregationResults<Document> aggregate = mongoTemplate.aggregate(typedAggregation, Document.class);
    List<Document> mappedResults = aggregate.getMappedResults();
    mappedResults.forEach(System.out::println);
}

示例二:每个作者的book的tag合集

@Test
public void test2() {
	UnwindOperation unwind = Aggregation.unwind("$tag");
    GroupOperation group = Aggregation
            .group("$author.name")
            .addToSet("$type").as("types");
    TypedAggregation<Book2> typedAggregation = Aggregation.newAggregation(Book2.class, unwind, group);
    AggregationResults<Document> aggregate = mongoTemplate.aggregate(typedAggregation, Document.class);
    List<Document> mappedResults = aggregate.getMappedResults();
    mappedResults.forEach(System.out::println);
}

示例三:联表查询用户以及对应的订单信息

@Test
public void test1() {
    LookupOperation lookup = Aggregation.lookup("order", "_id", "customerId", "order");
    TypedAggregation<Customer> orderTypedAggregation = Aggregation.newAggregation(Customer.class, lookup);
    AggregationResults<Document> aggregate = mongoTemplate.aggregate(orderTypedAggregation, Document.class);
    List<Document> mappedResults = aggregate.getMappedResults();
    mappedResults.forEach(System.out::println);
}

示例四:联表查询订单信息以及对应的商品项

@Test
public void test2() {
    LookupOperation lookup = Aggregation.lookup("orderItem", "_id", "orderId", "orderItem");
    TypedAggregation<Order> orderItemTypedAggregation = Aggregation.newAggregation(Order.class, lookup);
    AggregationResults<Document> aggregate = mongoTemplate.aggregate(orderItemTypedAggregation, Document.class);
    List<Document> mappedResults = aggregate.getMappedResults();
    mappedResults.forEach(System.out::println);
}

总结

本文是对MongoDB的学习,SpringBoot整合MongoDB的SpringData,配置文件中如何连接,实体类如何映射到文档,如何通过API进行集合操作和文档的增删查改。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Spring Cloud Gateway入门解读

    Spring Cloud Gateway入门解读

    本篇文章主要介绍了Spring Cloud Gateway入门解读,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-04-04
  • java文件操作工具类

    java文件操作工具类

    这篇文章主要为大家介绍了一个非常详细的java文件操作工具类,具有很强的实用性,感兴趣的小伙伴们可以参考一下
    2016-05-05
  • Java this 关键字的使用方法详解

    Java this 关键字的使用方法详解

    这篇文章主要介绍了Java this 关键字的使用方法详解的相关资料,希望通过本文能帮助到大家,让大家彻底理解掌握这部分内容,需要的朋友可以参考下
    2017-10-10
  • 解决IDEA 2020.1版本 maven Test命令出现导包错误的问题

    解决IDEA 2020.1版本 maven Test命令出现导包错误的问题

    这篇文章主要介绍了IDEA 2020.1版本 maven Test命令出现导包错误的问题及解决方法,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-08-08
  • Java中的PowerMock使用实践

    Java中的PowerMock使用实践

    这篇文章主要介绍了Java中的PowerMock使用实践,@PrepareForTest和@RunWith是成对出现的,一般@RunWith(PowerMockRunner.class),@PrepareForTest的值是引用的静态方法或私有方法的类,需要的朋友可以参考下
    2023-12-12
  • 一文秒懂Java enum常见的用法讲解

    一文秒懂Java enum常见的用法讲解

    这篇文章主要介绍了一文秒懂Java enum常见的用法讲解,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-12-12
  • JDK 7 新特性小结实例代码解析

    JDK 7 新特性小结实例代码解析

    这篇文章通过实例代码给大家介绍了JDK 7 新特性小结篇,感兴趣的朋友一起看看吧
    2018-03-03
  • 详解设计模式中的proxy代理模式及在Java程序中的实现

    详解设计模式中的proxy代理模式及在Java程序中的实现

    代理模式主要分为静态代理和动态代理,使客户端方面的使用者通过设置的代理来操作对象,下面来详解设计模式中的proxy代理模式及在Java程序中的实现
    2016-05-05
  • 基于java构造方法Vector遍历元素源码分析

    基于java构造方法Vector遍历元素源码分析

    本篇文章是关于ava构造方法Vector源码分析系列文章,本文主要介绍了Vector遍历元素的源码分析,有需要的朋友可以借鉴参考下,希望可以有所帮助
    2021-09-09
  • 关于SpringBoot使用@ExceptionHandler注解局部异常处理

    关于SpringBoot使用@ExceptionHandler注解局部异常处理

    这篇文章主要介绍了关于SpringBoot使用@ExceptionHandler注解局部异常处理,SpringBoot提供了多种方式来处理异常,在本文中,我们将介绍SpringBoot中的@ExceptionHandler注解,演示如何使用它进行局部异常处理
    2023-07-07

最新评论