Spring Boot Data MongoDB查询嵌套列表中匹配条件的Response字段
实现方案
你可以通过Spring Data MongoDB提供的聚合查询完成需求,也可以使用带$elemMatch的注解式查询,以下是两种可直接运行的实现方式:
方式1:使用MongoTemplate聚合查询(推荐,灵活度更高)
这种方式直接在数据库层面完成过滤,不需要拉取整个列表到内存过滤,性能更好。
首先注入MongoTemplate:
@Autowired private MongoTemplate mongoTemplate;
然后编写查询方法:
public Map<String, Object> getMatchedResponse(String mockName, String method, String endPoint, Map<String, Object> body, Map<String, String> params) { // 1. 匹配name等于指定mockName的Mock文档 MatchOperation matchMock = Aggregation.match(Criteria.where("name").is(mockName)); // 2. 拆分数组,把每个request变成独立文档 UnwindOperation unwindRequests = Aggregation.unwind("requests"); // 3. 匹配满足所有条件的request MatchOperation matchRequest = Aggregation.match( Criteria.where("requests.method").is(method) .and("requests.endPoint").is(endPoint) .and("requests.body").is(body) .and("requests.params").is(params) ); // 4. 仅返回需要的response字段 ProjectionOperation projectResponse = Aggregation.project() .and("requests.response").as("response") .andExclude("_id"); // 执行聚合 Aggregation aggregation = Aggregation.newAggregation(matchMock, unwindRequests, matchRequest, projectResponse); AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, Mock.class, Map.class); // 无匹配结果返回null即可 if (results.getMappedResults().isEmpty()) { return null; } return (Map<String, Object>) results.getUniqueMappedResult().get("response"); }
方式2:使用@Query注解+elemMatch(适合简单场景)
你也可以直接在Repository接口中定义查询方法,返回过滤后的Mock对象后再提取response:
首先定义MongoRepository:
public interface MockRepository extends MongoRepository<Mock, String> { @Query(value = "{ 'name': ?0, 'requests': { $elemMatch: { 'method': ?1, 'endPoint': ?2, 'body': ?3, 'params': ?4 } } }", fields = "{ 'requests.$': 1, '_id': 0 }") Mock findMatchedRequest(String mockName, String method, String endPoint, Map<String, Object> body, Map<String, String> params); }
调用时直接提取response即可:
public Map<String, Object> getResponse(String mockName, String method, String endPoint, Map<String, Object> body, Map<String, String> params) { Mock mock = mockRepository.findMatchedRequest(mockName, method, endPoint, body, params); if (mock == null || mock.getRequests().isEmpty()) { return null; } return mock.getRequests().get(0).getResponse(); }
注意事项
- 上述实现默认采用Map全量匹配逻辑,要求body、params的字段和值完全一致才会命中,符合所有条件全部匹配才返回结果的要求
- 如果你需要实现body/params部分字段匹配,把全等匹配条件改成对应键值匹配即可,比如
.and("requests.body.body").is("body")
内容的提问来源于stack exchange,提问作者Adarsh Balu
相关产品推荐
相关产品推荐

