mongodb和mongoTemplate复杂条件查询 (or与and)

本文详细介绍了如何在MongoDB中实现复杂查询,包括使用$and和$or操作符进行条件组合,以及如何在Spring框架下利用MongoTemplate进行相似查询。通过实例展示了如何根据不同的参数拼接查询条件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

 

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.youkuaiyun.com/tjbsl/article/details/80620303

使用Mongodb查询需要拼接复杂的or和and参数

MongoDb有表格:

1

"state1" : 11,

"state2" : 21,

"value" : 100

2

"state1" : 11,

"state2" : 22,

"value" : 300

3

"state1" : 11,

"state2" : 22,

"value" : 200

4

"state1" : 12,

"state2" : 21,

"value" : 300

 

要实现管理数据的如下SQL形式:

关系数据库:select * from where(state1=11 and state2=22) or value >300

首先使用MongoDB的方式查询:

分为以下几个步骤实现:

步骤一:实现 (state1=11 and state2=22)

db.getCollection('testOrAnd').find(

{$and:[{"state1":11},{"state2":22}]}

)

步骤二:使用or形式实现 value >300

db.getCollection('testOrAnd'). find(

{ $or:[{"value":{$gte:300}}] }

)

步骤三:将步骤一参数拼接到步骤二or条件

db.getCollection('testOrAnd').

find({$or:

[

{$and:[{"state1":11},{"state2":22}]},{"value":{$gte:300}}

]

})

 

最终实现结果:

 

使用spring-mongotemplate的方式查询(Criteria.where是静态方法):

分析查询方式,类似使用client的分析方式,分为以下几个步骤实现:

步骤一:实现 (state1=11 and state2=22)

query.addCriteria(

new Criteria().andOperator(

Criteria.where("state1").is(11),

Criteria.where("state2").is(22)

)

);

步骤二:使用or形式实现 value >300

query.addCriteria(

new Criteria().orOperator(

Criteria.where("value").gte(300)

)

);

步骤三:将步骤一参数拼接到步骤二or条件

query.addCriteria(

new Criteria().orOperator(

Criteria.where("value").gte(300),

new Criteria().andOperator(

Criteria.where("state1").is(11),

Criteria.where("state2").is(22)

)

)

);

 

升级查询,实际场景中要根据传输的参数是否为空,拼接查询条件:

(1)如果最外层是and关系(query.add多个creterria默认为and关系)

if(条件){

query.addCriteria(Criteria.where);

}

if(条件){

query.addCriteria(Criteria.where);

}

if(条件){

query.addCriteria(Criteria.where);

}

默认拼接的query条件为and形式。

(1)如果最外层是or关系(目前只想到此笨方法)

//1.拼接参数

Criteria operator1=null;

Criteria operator2=null;

if(1==1){//模拟判断条件

operator1 = new Criteria().andOperator(

Criteria.where("state1").is(11),

Criteria.where("state2").is(22)

);

}

if(1==1){//模拟判断条件

operator2 = Criteria.where("value").gte(300);

}

//2.判断参数

if(operator1!=null && operator2!=null){

query.addCriteria(new Criteria().orOperator(operator1,operator2));

}else if(operator1!=null){

query.addCriteria(operator1);

}else if(operator2!=null){

query.addCriteria(operator2);

}

 

补充:多个条件直接查询,默认是and形式

db.getCollection('testOrAnd').find({"state1":11,"state2":22})

<think>好的,用户之前已经询问过如何设计API参数来支持MongoDB中多组tagCodes的完全包含查询,并且得到了详细的回答。现在他们进一步询问如何在Java中实现这个需求,具体需要DTOMongoTemplate查询语句。 首先,我需要确认用户的使用环境技术栈。他们使用的是Java,并且用MongoTemplate来操作MongoDB,这说明他们可能是在Spring Boot项目中集成MongoDB。因此,需要提供符合Spring Data MongoDB规范的代码示例。 接下来,用户需要DTO(数据传输对象)的结构。根据之前的API设计,参数是一个二维数组tagsQuery,每个子数组表示一组必须完全包含的tagCode。所以在Java中,DTO应该包含一个List<List<String>>类型的字段来接收这个结构。同时,可能还需要分页参数,比如pageSizepageNumber,因此DTO中需要添加这些字段,并加上相应的验证注解,如@NotNull@Min,以确保参数的有效性。 然后是构建MongoDB查询的部分。用户使用MongoTemplate,所以需要构造CriteriaQuery对象。每个tagsQuery中的子数组需要转换成$all查询条件,然后组合成$or条件。同时,分页参数需要应用到查询中,使用skiplimit方法来实现分页,但需要注意性能问题,尤其是在处理大量数据时。 还需要考虑参数的验证,比如确保tagsQuery不为空,每个子数组至少有一个元素。这些可以通过Spring的验证注解来处理,或者在服务层进行手动检查,抛出异常提示客户端参数错误。 另外,用户可能没有明确提到分页,但根据之前的回答示例,分页参数被包含进来,所以需要确认是否需要分页功能。如果用户确实需要,那么在DTO中加入分页字段是合理的,并且在构建查询时应用分页参数。 最后,测试用例的编写也是一个重要的点,确保不同的查询组合能够正确生成对应的MongoDB查询语句。比如单个tagCode组、多个tagCode组以及分页的情况,都需要覆盖到。 可能存在的陷阱包括:参数传递格式错误,比如前端传递的JSON结构DTO不匹配;或者MongoDB查询条件构建错误,导致查询结果不符合预期。因此,在示例代码中需要详细展示如何正确构造这些条件,并处理可能的异常情况。 总结来说,用户需要一个完整的Java实现示例,涵盖DTO设计、参数验证、查询构建以及分页处理,确保他们能够直接将这些代码应用到项目中,并根据需要进行调整。同时,需要提醒他们注意性能优化参数验证的重要性,避免无效查询潜在的安全问题。</think>好的,我来帮你实现Java端的完整解决方案。以下是基于Spring Boot + MongoDB的详细实现: --- ### 一、DTO设计(含参数校验) ```java public class TagQueryRequest { @NotNull(message = "tagsQuery不能为空") @Size(min = 1, max = 10, message = "最多支持10组查询条件") private List<@Size(min = 1, max = 20, message = "每组最多20个tagCode") List<String>> tagsQuery; @Min(value = 1, message = "页码最小为1") private Integer pageNumber = 1; @Min(value = 1, message = "每页数量最小为1") @Max(value = 100, message = "单页最多100条") private Integer pageSize = 10; // 省略getter/setter } ``` --- ### 二、Repository查询实现 ```java @Repository public class CustomRepositoryImpl implements CustomRepository { @Autowired private MongoTemplate mongoTemplate; public Page<YourDocument> findByTagsQuery(TagQueryRequest request) { // 构建查询条件 Criteria criteria = buildCriteria(request.getTagsQuery()); Query query = new Query(criteria); // 分页处理 long total = mongoTemplate.count(query, YourDocument.class); query.skip((long) (request.getPageNumber() - 1) * request.getPageSize()) .limit(request.getPageSize()); // 执行查询 List<YourDocument> result = mongoTemplate.find(query, YourDocument.class); return new PageImpl<>(result, PageRequest.of(request.getPageNumber()-1, request.getPageSize()), total); } private Criteria buildCriteria(List<List<String>> tagsQuery) { List<Criteria> orCriteriaList = new ArrayList<>(); for (List<String> tagGroup : tagsQuery) { // 每个组生成$all条件 Criteria groupCriteria = Criteria.where("tagCodes").all(tagGroup); orCriteriaList.add(groupCriteria); } // 组合$or条件 return new Criteria().orOperator(orCriteriaList.toArray(new Criteria[0])); } } ``` --- ### 三、Service层调用示例 ```java @Service @RequiredArgsConstructor public class TagQueryService { private final CustomRepository customRepository; public Page<YourDocument> queryDocuments(TagQueryRequest request) { // 参数校验(JSR-303校验需配合@Valid使用) return customRepository.findByTagsQuery(request); } } ``` --- ### 四、Controller层示例 ```java @RestController @RequestMapping("/api/items") @Validated public class TagController { @Autowired private TagQueryService tagQueryService; @PostMapping("/search") public ResponseEntity<Page<YourDocument>> search( @RequestBody @Valid TagQueryRequest request) { return ResponseEntity.ok(tagQueryService.queryDocuments(request)); } } ``` --- ### 五、MongoDB查询语句对应关系 当请求参数为: ```json { "tagsQuery": [ ["tag1", "tag2"], ["tag3"] ], "pageNumber": 2, "pageSize": 20 } ``` 生成的MongoDB查询语句为: ```javascript db.collection.find({ $or: [ { tagCodes: { $all: ["tag1", "tag2"] } }, { tagCodes: { $all: ["tag3"] } } ] }) .skip(20) .limit(20) ``` --- ### 六、关键点说明 1. **参数校验**: - 使用JSR-303注解实现基础校验 - 嵌套集合的校验需要Java 8+ - 建议补充`@Valid`触发校验 2. **性能优化**: ```java // 可添加索引提升查询性能 @Document public class YourDocument { @Indexed private List<String> tagCodes; } ``` 3. **复杂查询扩展**: ```java // 如需组合其他查询条件 Criteria combined = new Criteria().andOperator( buildCriteria(tagsQuery), Criteria.where("status").is("ACTIVE") ); ``` 4. **空值处理**:建议在DTO中设置默认分页参数 --- ### 七、测试用例参考 ```java @Test public void testTagQuery() { // 构建测试请求 TagQueryRequest request = new TagQueryRequest(); request.setTagsQuery(List.of( List.of("electronics", "onsale"), List.of("furniture") )); request.setPageNumber(1); request.setPageSize(10); // 验证生成的Criteria Criteria criteria = buildCriteria(request.getTagsQuery()); assertThat(criteria.getCriteriaObject().toJson()) .contains("$or") .contains("$all"); } ``` 这种实现方式既保持了API的清晰结构,又充分利用了Spring Data MongoDB的特性,同时通过分层设计保证了代码的可维护性。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值