首页 > 解决方案 > QueryDSL谓词绑定多个路径之间的“或”

问题描述

我有一个 Spring Boot Rest API 女巫使用Querydsl谓词进行过滤,我使用MongoRepository上的QuerydslBinderCustomizer绑定属性路径以自定义查询。

为同一路径设置多个搜索值时的默认行为是这些值之间的 OR 运算符。

但是当使用多个路径并使用 AND 运算符时。

我想要做的是在多个选择的路径之间放置一个 OR 运算符。

我发现了这个非常清晰的文档,但没有在其中找到答案:https ://gt-tech.bitbucket.io/spring-data-querydsl-value-operators/README.html

今天我有:

控制器

public Page<Document> find(
            @QuerydslPredicate(root = Document.class) Predicate predicate) {
        return repository.findAll(predicate);
    }

存储库

public interface Repository extends
        MongoRepository<Document, String>,
        QueryDslPredicateExecutor<EventRuleDocument>,
        QuerydslBinderCustomizer<QEventRuleDocument> {

    @Override
    default void customize(QuerydslBindings bindings, QDocument doc) {
        bindings.bind(doc.prop1).first(StringExpression::containsIgnoreCase);
        bindings.bind(doc.prop2).first(StringExpression::containsIgnoreCase);
        bindings.bind(doc.prop3).first(StringExpression::containsIgnoreCase);
    }
}

女巫给了我谓词:prop1 == v1 AND prop2 == v2 AND prop3 == v3

我想要实现的是:prop1 == v1 OR prop2 == v2 OR prop3 == v3

这可以使用QuerydslBinderCustomizer吗?

还是我必须创建自定义控制器和/或存储库方法?

标签: javaspring-bootspring-dataspring-data-mongodbquerydsl

解决方案


@Override
default void customize(QuerydslBindings bindings, QDocument root) {

StringPath[] multiPropertySearchPaths = new StringPath[] {root.prop1, root.prop2, root.prop3};

/**
 * Binds prop1, prop2 and prop3 in OR clause
 * This binding will activate when one of the given properties are searched in query params
 */
bindings.bind(multiPropertySearchPaths).all(new MultiValueBinding<StringPath, String>() {
    @Override
    public Predicate bind(StringPath path, Collection<? extends String> values) {
        BooleanBuilder predicate = new BooleanBuilder();
        // Bind paths present in array multiPropertySearchPaths with incoming values
        for (StringPath propertyPath : multiPropertySearchPaths) {
            values.forEach(value -> predicate.or(propertyPath.containsIgnoreCase(value)));
        }
        return predicate;
    }
});
}

它将生成如下 sql:

select * from document
where
    lower(document.prop1) like ?1 
    or lower(document.prop2) like ?1 
    or lower(document.prop3) like ?1

推荐阅读