Overview
本教程向您展示如何使用 Spring Data 创建高级查询以与MongoDB交互。您学习;了解如何使用 MongoRepository 接口和 MongoTemplate 类来执行筛选、更新和聚合数据等操作。
注意
本教程要求您对 Spring Data 和MongoDB有基本了解。有关将 Spring Data 与MongoDB结合使用的介绍,请参阅 Spring Data Framework 集成教程。
先决条件
您必须拥有以下物品才能完成本教程:
来自 spring-data-unlocked 示例存储库的源代码。按照存储库自述文件中的说明设立和运行项目。
您首选的 IDE。
数据模型
本教程使用具有以下结构的ACID 事务数据模型:
{ "id": "672182814338f60133ee26e1", "transactionType": "Debit", "amount": 888.0, "currency": "USD", "status": "In Progress", "description": "Transfer to Ricardo", "createdAt": "2024-10-09T14:00:00", "accountDetails": { "originator": { "accountNumber": "2376543213", "name": "Maria", "bank": "Bank G" }, "beneficiary": { "accountNumber": "2234987651", "name": "Ricardo Mello", "bank": "Bank V" } } }
Tutorial
本教程中的应用程序是管理客户记录和事务的REST API 。
本教程向您展示如何执行以下操作:
使用
MongoRepository创建派生查询。使用
@Query注解创建查询。使用
@Update注解更新数据。查看聚合管道方法。
实施分页。
使用
MongoTemplate进行灵活操作。
使用 MongoRepository 创建派生查询。
导航到 spring-data-unlocked项目中的 src/main/java/com/mongodb/resources目录,然后打开 TransactionRepository 界面。该接口包含以下按类型查找事务的方法:
List<Transaction> findByTransactionType(String type);
Spring Data 使用方法名称来创建查询。 findBy 前缀指示 Spring Data 创建查询,而 TransactionType 指定要过滤的字段。
您可以通过将以下行添加到 application.properties文件来启用调试日志记录,以查看生成的查询:
logging.level.org.springframework.data.mongodb=DEBUG
提示
确保 application.properties文件位于类路径中,以便 Spring Boot 可以加载指定的属性。
运行findByTransactionType查询时,控制台会显示类似于以下内容的输出:
2024-10-15T18:30:33.855-03:00 DEBUG 28992 [SpringShop] [nio-8080-exec-6] o.s.data.mongodb.core.MongoTemplate: find using query: { "transactionType" : "Transfer"} fields: Document{{}} sort: { "transactionType" : "Transfer"} for class: class com.mongodb.Transaction in collection: transactions
TransactionRepository 接口还包括以下方法,用于按金额查找事务和按类型删除事务:
List<Transaction> findByAmountGreaterThan(double amount); void deleteByTransactionType(String type);
使用 @Query 注解创建查询。
TransactionRepository 定义了一个 findByStatus() 方法,该方法使用 @Query 注解按 status字段值查找事务。此方法仅返回特定字段并对结果进行排序。
List<Transaction> findByStatus(String status);
@Query 注解中的参数指定以下内容:
value指定过滤条件。fields定义要包含在结果中的字段。sort按createdAt字段值降序对结果进行排序。
要学习;了解有关@Query 注解的更多信息,请参阅 Spring Data MongoDB文档。
使用 @Update 注解更新数据。
TransactionRepository 接口包含一个结合使用 @Query 和 @Update 注解来更新ACID 事务状态的方法:
void updateStatus(String id, String status);
@Query 注释通过ID查找文档,@Update 注释修改状态字段。
要学习;了解更多信息,请参阅有关更新操作的 Spring Data MongoDB文档。
将错误事务导出到新集合。
TransactionRepository 接口还包括一个使用 $out 阶段将错误事务复制到新集合的方法:
void exportErrorTransactions();
调用此方法时, MongoDB会创建一个名为 error_transactions 的新集合,并插入所有处于错误状态的文档。
重要
在生产中使用此阶段之前,请查看 $out操作符文档。如果目标集合已存在,则$out 阶段会将其替换。
查看文本搜索注释。
src/main/java/com/mongodb/resources目录中的 SearchAggregate.java文件包含以下代码,用于创建执行文本搜索的自定义注解。
import org.springframework.data.mongodb.repository.Aggregation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; SearchAggregate { }
TransactionRepository 接口包含以下使用该注解的代码:
List<Transaction> search(String query, String path);
实施分页。
MongoRepository 接口扩展了 PagingAndSortingRepository,后者提供分页支持。打开 TransactionService 类并添加以下方法:
public Page<Transaction> findPageableTransactions( Pageable pageable ) { return transactionRepository.findAll(pageable); }
src/main/java/com/mongodb/application/web目录中的 TransactionController 类包含以下接受分页参数的控制器方法:
public PagedModel<Transaction> findAll( int page, int sizePerPage, String sortField, Sort.Direction sortDirection) { Pageable pageable = PageRequest.of(page, sizePerPage, Sort.by(sortDirection, sortField)); return new PagedModel<>(transactionService.findPageableTransactions(pageable)); }
在应用程序运行时,通过从终端运行以下命令来调用此端点:
curl --location 'http://localhost:8080/transactions?page=0&sizePerPage=10&sortField=description&sortDirection=ASC'
配置 MongoTemplate。
在MongoDB上执行操作时,MongoTemplate 类比 MongoRepository 类更灵活。在以下步骤中,您学习;了解如何使用 MongoTemplate 执行批量操作、查询和聚合。
导航至 src/main/java/com/mongodb/resources目录以查看名为 MongoConfig.java 的配置类,该类用于设置 MongoTemplate:
package com.mongodb; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClients; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.MongoTemplate; public class MongoConfig { public MongoClient mongoClient() { MongoClientSettings settings = MongoClientSettings.builder() .applyConnectionString(new ConnectionString("<your connection string>")) .build(); return MongoClients.create(settings); } MongoOperations mongoTemplate(MongoClient mongoClient) { return new MongoTemplate(mongoClient, "springshop"); } }
执行批量插入操作。
src/main/java/com/mongodb/domain/service目录中的 CustomerService 类包含以下一次性插入多个文档的方法:
public int bulkCustomerSample(List<Customer> customerList) { if (findAll().isEmpty()) { BulkWriteResult result = mongoOperations.bulkOps(BulkOperations.BulkMode.ORDERED, Customer.class) .insert(customerList) .execute(); return result.getInsertedCount(); } return 0; }
bulkOps 方法创建批量操作,将所有文档插入列表中。
使用 MongoTemplate 查询文档。
CustomerService 类包含通过电子邮件查找客户的方法:
public Customer findCustomerByEmail(String email) { return mongoOperations.query(Customer.class) .matching(query(where("email").is(email))) .one() .orElseThrow(() -> new RuntimeException("Customer not found with email: " + email)); }
query 方法接受定义过滤的Criteria对象。您可以使用 gt()、lt()、and() 和 or() 等方法来构建复杂查询。
要学习;了解更多信息,请参阅 Criteria 类文档。
使用 MongoTemplate 执行聚合。
src/main/java/com/mongodb/domain/model目录中的 CustomersByCity 类包含以下保存聚合结果的记录:
public record CustomersByCity( String id, int total ){}
CustomerService.java文件包含按城市计算客户数量的方法:
public List<CustomersByCity> totalCustomerByCity() { TypedAggregation<Customer> aggregation = newAggregation(Customer.class, group("address.city") .count().as("total"), Aggregation.sort(Sort.Direction.ASC, "_id"), project(Fields.fields("total", "_id"))); AggregationResults<CustomersByCity> result = mongoOperations.aggregate(aggregation, CustomersByCity.class); return result.getMappedResults(); }
此方法按城市对客户进行分组,并计算每个城市的客户数量。
其他资源
要学习;了解有关 Spring Data MongoDB 的更多信息,请参阅 Spring Data MongoDB文档。