The Hibernate Search 6 documentation shows one example of how to dynamically generate a single bool() in the where clause:
MySearchParameters searchParameters = getSearchParameters();
List<Book> hits = searchSession.search( Book.class )
.where( f -> f.bool( b -> {
b.must( f.matchAll() );
if ( searchParameters.getGenreFilter() != null ) {
b.must( f.match().field( "genre" )
.matching( searchParameters.getGenreFilter() ) );
}
if ( searchParameters.getFullTextFilter() != null ) {
b.must( f.match().fields( "title", "description" )
.matching( searchParameters.getFullTextFilter() ) );
}
if ( searchParameters.getPageCountMaxFilter() != null ) {
b.must( f.range().field( "pageCount" )
.atMost( searchParameters.getPageCountMaxFilter() ) );
}
} ) )
.fetchHits( 20 );
1 . How would I modify your above example, from a single bool()
f → f.bool
to conditionally nest multiple bools, using if or for-loops?
2 . Similarly, how can I conditionally decide if I want to add .sort() to the above example, when “if (searchParameters.getGenreFilter() != null)” is true?
Thanks for the assist.
Boolean predicates are just like any other predicate. You can call f.bool()
again to create another boolean predicate and nest it.
MySearchParameters searchParameters = getSearchParameters();
List<Book> hits = searchSession.search( Book.class )
.where( f -> f.bool( b -> {
b.must( f.matchAll() );
List<Genre> genresFilter = searchParameters.getGenresFilter();
if ( !genresFilter.isEmpty() ) {
b.must( f.bool( b2 -> {
for ( Genre genre : genresFilter ) {
b2.should( f.match().field( "genre" ).matching( genre ) );
} ) );
}
} ) )
.fetchHits( 20 );
And if you have a pre-determined number of clauses, you don’t even need a lambda:
MySearchParameters searchParameters = getSearchParameters();
List<Book> hits = searchSession.search( Book.class )
.where( f -> f.bool( b -> {
b.must( f.matchAll() );
GenreFilter genresFilter = searchParameters.getGenresFilter();
if ( genresFilter != null ) {
b.must( f.bool()
.should( f.match().field( "genre" )
.matching( genresFilter.getGenre1() ) )
.should( f.match().field( "genre" )
.matching( genresFilter.getGenre2() ) ) );
}
} ) )
.fetchHits( 20 );
This is documented as well:
MySearchParameters searchParameters = getSearchParameters();
List<Book> hits = searchSession.search( Book.class )
.where( f -> f.matchAll() )
.sort( f -> f.composite( b -> {
for ( MySort mySort : searchParameters.getSorts() ) {
switch ( mySort.getType() ) {
case GENRE:
b.add( f.field( "genre_sort" ).order( mySort.getOrder() ) );
break;
case TITLE:
b.add( f.field( "title_sort" ).order( mySort.getOrder() ) );
break;
case PAGE_COUNT:
b.add( f.field( "pageCount" ).order( mySort.getOrder() ) );
break;
}
}
} ) )
.fetchHits( 20 );