我有这个查询界面:
public interface IMyDocDao extends MongoRepository<MyDoc, String> {
@Query(value = "{ 'stuff.in.nested.doc' : ?0, 'another.stuff.in.nested.doc' : ?1 }")
List<MyDoc> findByFoo(String foo, String bar);
}
如果来电findByFoo("a", "b")
可以正常使用。
如果来电findByFoo("", "b")
,则会返回第一个参数为空白且第二个参数为&#34; b&#34;的文档。
如果来电findByFoo(null, "b")
,则会返回没有属性stuff.in.nested.doc
的文档,第二个是&#34; b&#34;。
有没有办法告诉查询忽略参数foo
以防空白/空?
换句话说,我希望findByFoo("", "b")
只返回参数bar
为&#34; b&#34;的所有文档,忽略第一个参数。
由于参数数量可能会增加,因此编写多个方法不是一个可扩展的选项。
答案 0 :(得分:0)
一个相对简单的解决方案是使用here所述的自定义存储库实现。对于我的示例代码,它会给出:
@Autowired
MongoTemplate mongoTemplate;
@Override
public List<MyDoc> findByCriteria(Map<String, String> requestCriteria) {
Criteria criteria = new Criteria();
// Foo
if (requestCriteria.containsKey("foo")) {
if (!StringUtils.isBlank(requestCriteria.get("foo"))) {
criteria = criteria.and("stuff.in.nested.doc").is(requestCriteria.get("foo"));
}
}
// Bar
if (requestCriteria.containsKey("bar")) {
if (!StringUtils.isBlank(requestCriteria.get("bar"))) {
criteria = criteria.and("another.stuff.in.nested.doc").is(requestCriteria.get("bar"));
}
}
return mongoTemplate.find(new Query(criteria), MyDoc.class, "mydoc");
}
另一个解决方案可能是使用QueryDSL(来自Marc Tarin的评论),我尚未对其进行测试。
答案 1 :(得分:0)
使用QueryDSL快速制作的解决方案:
public interface IMyDocDao extends MongoRepository<MyDoc, String>,
QueryDslPredicateExecutor<MyDoc>,
QuerydslBinderCustomizer<MyDoc> {
@Override
default void customize(QuerydslBindings bindings, QMyDoc myDoc) { // QMyDoc is generated by QueryDSL at build time
bindings.bind(MyDoc.class)
.first((StringPath path, String value) -> {
if (!value.isEmpty()) {
path.eq(value);
}
});
}
}
然后在你的控制器中注入一个IMyDocDao:
@RestController
public class MyDocController {
@Autowire
private IMyDocDao myDocDao;
@GetMapping("myDoc/search/query")
public List<MyDoc> query(@QuerydslPredicate(root = MyDoc.class) Predicate predicate) {
return myDocDao(predicate);
}
GET .../myDoc/search/query?stuff.in.nested.doc=a&another.stuff.in.nested.doc=b
应该返回预期的结果(尽管没有经过测试)。