【问题标题】:Multi-column "OR" in Spring Data Rest with QueryDslSpring Data Rest 中的多列“OR”与 QueryDsl
【发布时间】:2020-03-09 02:01:27
【问题描述】:

Spring (Boot) Data Rest 和 QueryDsl 是否可以跨多个列执行“或”搜索?我已经自定义了我的绑定,以便在多次出现相同的搜索路径时执行“或”搜索(MultiValueBinding)。 myentity?name=foo&name=bar 将返回 name 属性包含 foobar 的所有实体。

@Entity
MyEntity {
    @Id
    Long id;
    String name;
    String email;
}

@RepositoryRestResource(path = "myentity")
public interface MyEntityRepository extends CrudRepository<MyEntity, Long>, ,
        QuerydslPredicateExecutor<MyEntity>, QuerydslBinderCustomizer<QMyEntity> {
    @Override
    default void customize(QuerydslBindings bindings, QMyEntity root) {
        bindings.bind(root.id).first(NumberExpression::eq);
        bindings.bind(String.class).all((StringPath path, Collection<? extends String> values) -> {
            BooleanBuilder predicate = new BooleanBuilder();
            values.forEach(value -> predicate.or(path.containsIgnoreCase(value)));
            return Optional.of(predicate);
        });
    }
}

如果不实现自定义控制器,是否可以通过“或”连接多个路径中的搜索,以便myentity?name=foo&amp;email=bar 将返回名称属性包含“foo”的结果电子邮件属性包含“酒吧”。或者定义一个自定义路径,然后用于在多列中进行搜索?例如myentity?nameOrEmail=foo

【问题讨论】:

  • 我已经自定义了我的绑定,以便在多次出现相同的搜索路径时执行“或”搜索。顺便说一句,这应该是默认行为,不需要任何绑定自定义。
  • @AlanHay 感谢您提供的信息,我在阅读文档时错过了这一点。仅当您需要与 equals 不同的表达式时(例如我的示例中的 containsIgnoreCase),才需要绑定自定义。 docs.spring.io/spring-data/jpa/docs/current/reference/html/…

标签: java spring-boot spring-data spring-data-rest querydsl


【解决方案1】:

你可以只使用这个库:https://github.com/turkraft/spring-filter

它将让您运行搜索查询,例如:

/search?filter= 平均(收视率)> 4.5 brand.name in (“奥迪”、“路虎”)(年> 2018 公里 50000) 和颜色 : '白色' 意外是空的

您也可以查看https://github.com/jirutka/rsql-parser,但它有点过时了

【讨论】:

    【解决方案2】:

    尝试使用此实现:

    @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
    

    【讨论】:

    • 感谢您的努力,但这并不能解决我的问题:像 document?prop1=valueProp1&amp;prop2=valueProp2 这样的请求会产生一个 SQL 查询,它将搜索所有 multiPropertySearchPaths 中的所有提交值。因此,它会找到document.prop2 中存在“valueProp1”的文档。我需要的是一个 where 子句,例如 where lower(document.prop1) like 'valueProp1' or lower(document.prop2) like 'valueProp2'
    猜你喜欢
    • 2016-10-26
    • 2020-01-18
    • 2020-08-18
    • 2017-11-24
    • 2020-06-16
    • 1970-01-01
    • 2013-10-31
    • 2012-11-09
    • 2016-05-12
    相关资源
    最近更新 更多