首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >将嵌套Hibernate搜索5谓词转换为Hibernate搜索6

将嵌套Hibernate搜索5谓词转换为Hibernate搜索6
EN

Stack Overflow用户
提问于 2022-03-14 16:06:31
回答 1查看 409关注 0票数 0

在将应用程序从Hibernate搜索5转换为6的过程中,我阅读了很多文档,特别是关于如何在简单场景中转换查询DSL的单个/#查询-引用,但是如何将谓词嵌套到其他嵌套谓词中,然后在更大的查询中将它们与其他谓词结合起来呢?

在Hibernate搜索5中,我们将使用queryBuilder.bool()创建一个BooleanJunction,然后通过在bool上调用createQuery来在另一个BooleanJunction中添加它,并反复创建嵌套谓词查询。

我所讨论的转换代码类型的示例:

代码语言:javascript
代码运行次数:0
运行
复制
    BooleanJunction vendorNameBool = queryBuilder.bool();
    BooleanJunction nameBool = queryBuilder.bool();
    
    nameBool.must(
        qb.keyword()
            .onField(CompanyName)
            .matching(nameToken1)
            .createQuery()
    );
    
    nameBool.must(
        qb.keyword()
            .onField(CompanyName)
            .matching(nameToken2)
            .createQuery()
    );

    vendorNameBool.should(nameBool.createQuery);
    
    // do vendorNameBool.should(...) for as many vendor Names that exist, then createQuery 
    probableVendorNamesQuery = vendorNameBool.createQuery();
    
    // creating a number of Queries from various bools and then combining them:
    Query taxIdOrVendorNameOrPhoneNumberQuery = qb.bool()
        .should(probableVendorNamesQuery)
        .should(taxIdQuery)
        .should(phoneNumberQuery)
        .createQuery();
        
    //and add to the final BooleanQuery along with other Query pieces
    
    Query idQuery = getIdQuery();
    Query fileIdQuery = getFileIdQuery();
    
    BooleanQuery.Builder theQuery = new BooleanQuery.Builder();
    theQuery.add(taxIdOrVendorNameOrPhoneNumberQuery, MUST);
    theQuery.add(fileIdQuery, MUST);    
    theQuery.add(idQuery, MUST_NOT);    
    
    BooleanQuery probableQuery = theQuery.build();
     
    // add some projections and execute query

大多数HS6代码示例都以lambda形式出现。有一节这里提供了一个创建非lamba谓词的简单示例,并将它们添加到list中,但是,例如,您将如何将谓词列表添加到外部must子句中,然后将该must子句以及另一个must子句添加到外部“必须”子句,等等。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-03-15 07:38:44

就我个人而言,我只需要使用lambda语法并嵌套第二个lambda。修改迁移指南中的示例:

代码语言:javascript
代码运行次数:0
运行
复制
 MySearchParameters searchParameters = ...;
 SearchSession session = Search.session( entityManager );
 List<Book> hits = searchSession.search( Book.class )
         .where( f -> f.bool( b -> {
             b.must( f.matchAll() );
             if ( searchParameters.getSearchTerms() != null ) {
                 b.must( f.simpleQueryString().fields( "title", "description" )
                         .matching( searchParameters.getSearchTerms() )
                         .defaultOperator( BooleanOperator.AND ) );
             }
             // ...
             // BEGIN NEW CODE
             SomeComplexParameter complexParam = searchParameters.getSomeComplexParameter();
             if ( complexParam != null ) {
                 b.must( f.bool( b2 -> {
                     b2.should( f.match().field( "someField1" )
                         .matching( complexParam.getSomeField1() ) );
                     b2.should( f.match().field( "someField2" )
                         .matching( complexParam.getSomeField2() ) );
                 } ) );
             }
             // END NEW CODE
         } ) )
         .fetchHits( params.getPageIndex() * params.getPageSize(), params.getPageSize() );

如果在编译时知道子句的数量,甚至不需要第二个lambda:

代码语言:javascript
代码运行次数:0
运行
复制
 MySearchParameters searchParameters = ...;
 SearchSession session = Search.session( entityManager );
 List<Book> hits = searchSession.search( Book.class )
         .where( f -> f.bool( b -> {
             b.must( f.matchAll() );
             if ( searchParameters.getSearchTerms() != null ) {
                 b.must( f.simpleQueryString().fields( "title", "description" )
                         .matching( searchParameters.getSearchTerms() )
                         .defaultOperator( BooleanOperator.AND ) );
             }
             // ...
             // BEGIN NEW CODE
             SomeComplexParameter complexParam = searchParameters.getSomeComplexParameter();
             if ( complexParam != null ) {
                 b.must( f.bool()
                         .should( f.match().field( "someField1" )
                             .matching( complexParam.getSomeField1() ) )
                         .should( f.match().field( "someField2" )
                             .matching( complexParam.getSomeField2() ) ) );
             }
             // END NEW CODE
         } ) )
         .fetchHits( params.getPageIndex() * params.getPageSize(), params.getPageSize() );

如果您真的不想在顶层使用lambda(为什么?),至少可以将lambda用于嵌套谓词:

代码语言:javascript
代码运行次数:0
运行
复制
MySearchParameters searchParameters = ...;
SearchSession session = Search.session( entityManager );
SearchPredicateFactory pf = session.scope( Book.class ).predicate();
List<SearchPredicate> predicates = new ArrayList<>();

if ( searchParameters.getSearchTerms() != null ) {
    predicates.add( pf.simpleQueryString().fields( "title", "description" )
            .matching( searchParameters.getSearchTerms() )
            .defaultOperator( BooleanOperator.AND )
            .toPredicate() );
}

// ...

// BEGIN NEW CODE
SomeComplexParameter complexParam = searchParameters.getSomeComplexParameter();
if ( complexParam != null ) {
    predicates.add( pf.bool( b -> {
        b.should( pf.match().field( "someField1" )
            .matching( complexParam.getSomeField1() ) );
        b.should( pf.match().field( "someField2" )
            .matching( complexParam.getSomeField2() ) );
    } )
            .toPredicate() );
}
// END NEW CODE

List<Book> hits = searchSession.search( Book.class )
        .where( f -> f.bool( b -> {
            b.must( f.matchAll() );
            for ( SearchPredicate predicate : predicates ) {
                b.must( predicate );
            }
        } )

在这里,只要事先知道谓词的数量,就不需要lambda:

代码语言:javascript
代码运行次数:0
运行
复制
MySearchParameters searchParameters = ...;
SearchSession session = Search.session( entityManager );
SearchPredicateFactory pf = session.scope( Book.class ).predicate();
List<SearchPredicate> predicates = new ArrayList<>();

if ( searchParameters.getSearchTerms() != null ) {
    predicates.add( pf.simpleQueryString().fields( "title", "description" )
            .matching( searchParameters.getSearchTerms() )
            .defaultOperator( BooleanOperator.AND )
            .toPredicate() );
}

// ...

// BEGIN NEW CODE
SomeComplexParameter complexParam = searchParameters.getSomeComplexParameter();
if ( complexParam != null ) {
    predicates.add( pf.bool()
            .should( pf.match().field( "someField1" )
                .matching( complexParam.getSomeField1() ) )
            .should( pf.match().field( "someField2" )
                 .matching( complexParam.getSomeField2() ) )
            .toPredicate() );
}
// END NEW CODE

List<Book> hits = searchSession.search( Book.class )
        .where( f -> f.bool( b -> {
            b.must( f.matchAll() );
            for ( SearchPredicate predicate : predicates ) {
                b.must( predicate );
            }
        } )
        .fetchHits( params.getPageIndex() * params.getPageSize(), params.getPageSize() );

最后,如果您真的想完全远离lambdas (但同样,为什么?),您可能可以这样做。但是,请注意,BooleanPredicateClausesStep的泛型类型参数在Hibernate搜索的次要版本中可能会发生变化,因此在升级时,这段代码更有可能中断。

代码语言:javascript
代码运行次数:0
运行
复制
MySearchParameters searchParameters = ...;
SearchSession session = Search.session( entityManager );
SearchPredicateFactory pf = session.scope( Book.class ).predicate();
BooleanPredicateClausesStep<?> boolStep = pf.bool();

boolStep.must( f.matchAll() );

if ( searchParameters.getSearchTerms() != null ) {
    boolStep.must( pf.simpleQueryString().fields( "title", "description" )
            .matching( searchParameters.getSearchTerms() )
            .defaultOperator( BooleanOperator.AND ) );
}

// ...

SomeComplexParameter complexParam = searchParameters.getSomeComplexParameter();
if ( complexParam != null ) {
    BooleanPredicateClausesStep<?> boolStep2 = pf.bool();
    boolStep2.should( f.match().field( "someField1" )
            .matching( complexParam.getSomeField1() ) );
    boolStep2.should( f.match().field( "someField2" )
            .matching( complexParam.getSomeField2() ) );
    boolStep.must( boolStep2 );
}

SearchPredicate boolPredicate = boolStep.toPredicate();

List<Book> hits = searchSession.search( Book.class )
        .where( boolPredicate )
        .fetchHits( params.getPageIndex() * params.getPageSize(), params.getPageSize() );

如果使用JDK 11进行编译,更健壮的解决方案是使用var关键字:

代码语言:javascript
代码运行次数:0
运行
复制
MySearchParameters searchParameters = ...;
SearchSession session = Search.session( entityManager );
SearchPredicateFactory pf = session.scope( Book.class ).predicate();
var boolStep = pf.bool();

boolStep.must( f.matchAll() );

if ( searchParameters.getSearchTerms() != null ) {
    boolStep.must( pf.simpleQueryString().fields( "title", "description" )
            .matching( searchParameters.getSearchTerms() )
            .defaultOperator( BooleanOperator.AND ) );
}

// ...

SomeComplexParameter complexParam = searchParameters.getSomeComplexParameter();
if ( complexParam != null ) {
    var boolStep2 = pf.bool();
    boolStep2.should( f.match().field( "someField1" )
            .matching( complexParam.getSomeField1() ) );
    boolStep2.should( f.match().field( "someField2" )
            .matching( complexParam.getSomeField2() ) );
    boolStep.must( boolStep2 );
}

SearchPredicate boolPredicate = boolStep.toPredicate();

List<Book> hits = searchSession.search( Book.class )
        .where( boolPredicate )
        .fetchHits( params.getPageIndex() * params.getPageSize(), params.getPageSize() );
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71470810

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档