2020-03-21

Hibernate Search - Sort DSL

Sort DSL

By default, query results are sorted by relevance. Other sorts, including the sort by field value, can be configured when building the search query:

Using custom sorts

SearchSession searchSession = Search.session( entityManager );

List<Book> result = searchSession.search( Book.class ) 
        .where( f -> f.matchAll() )
        .sort( f -> f.field( "pageCount" ).desc() 
                .then().field( "title_sort" ) )
        .fetchHits( 20 ); 
Start building the query as usual.
Mention that the results of the query are expected to be sorted on field "pageCount" in descending order, then (for those with the same page count) on field "title_sort" in ascending order. If the field does not exist or cannot be sorted on, an exception will be thrown.
Fetch the results, which will be sorted according to instructions.

Using custom sorts — object-based syntax

SearchSession searchSession = Search.session( entityManager );

SearchScope<Book> scope = searchSession.scope( Book.class );

List<Book> result = searchSession.search( scope )
        .where( scope.predicate().matchAll().toPredicate() )
        .sort( scope.sort()
                .field( "pageCount" ).desc()
                .then().field( "title_sort" )
                .toSort() )
        .fetchHits( 20 );

score: sort by matching score (relevance)
Sorting by relevance

List<Book> hits = searchSession.search( Book.class )
        .where( f -> f.match().field( "title" )
                .matching( "robot dawn" ) )
        .sort( f -> f.score() )
        .fetchHits( 20 );

indexOrder: sort according to the order of documents on storage
Sorting according to the order of documents on storage

List<Book> hits = searchSession.search( Book.class )
        .where( f -> f.matchAll() )
        .sort( f -> f.indexOrder() )
        .fetchHits( 20 );

field: sort by field values
Sorting by field values

List<Book> hits = searchSession.search( Book.class )
        .where( f -> f.matchAll() )
        .sort( f -> f.field( "title_sort" ) )
        .fetchHits( 20 );

Sorting by field values, with missing values in first position
List<Book> hits = searchSession.search( Book.class )
        .where( f -> f.matchAll() )
        .sort( f -> f.field( "pageCount" ).missing().first() )
        .fetchHits( 20 );

Sorting by field values, with missing values in last position
List<Book> hits = searchSession.search( Book.class )
        .where( f -> f.matchAll() )
        .sort( f -> f.field( "pageCount" ).missing().last() )
        .fetchHits( 20 );

Sorting by field values, with missing values replaced by a given value
List<Book> hits = searchSession.search( Book.class )
        .where( f -> f.matchAll() )
        .sort( f -> f.field( "pageCount" ).missing().use( 300 ) )
        .fetchHits( 20 );


distance: sort by distance to a point
Sorting by distance to a point

GeoPoint center = GeoPoint.of( 47.506060, 2.473916 );
List<Author> hits = searchSession.search( Author.class )
        .where( f -> f.matchAll() )
        .sort( f -> f.distance( "placeOfBirth", center ) )
        .fetchHits( 20 );

composite: combine sorts
Sorting by multiple composed sorts using composite()

List<Book> hits = searchSession.search( Book.class )
        .where( f -> f.matchAll() )
        .sort( f -> f.composite()
                .add( f.field( "genre_sort" ) )
                .add( f.field( "title_sort" ) ) )
        .fetchHits( 20 );

Sorting by multiple composed sorts using then()
List<Book> hits = searchSession.search( Book.class )
        .where( f -> f.matchAll() )
        .sort( f -> f.field( "genre_sort" )
                .then().field( "title_sort" ) )
        .fetchHits( 20 );

Easily composing sorts dynamically with the lambda syntax
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 );
Get a custom object holding the search parameters provided by the user through a web form, for example.
Call .composite(Consumer). The consumer, implemented by a lambda expression, will receive a builder as an argument and will add sorts to that builder as necessary.
Inside the lambda, the code is free to do whatever is necessary before adding sorts. In this case, we iterate over user-selected sorts and add sorts accordingly.
The hits will be sorted according to sorts added by the lambda expression.

Elasticsearch: fromJson

Sorting by a native Elasticsearch JSON sort provided as a JsonObject
JsonObject jsonObject =
        /* ... */;
List<Book> hits = searchSession.search( Book.class )
        .extension( ElasticsearchExtension.get() )
        .where( f -> f.matchAll() )
        .sort( f -> f.fromJson( jsonObject ) )
        .fetchHits( 20 );

Sorting by a native Elasticsearch JSON sort provided as a JSON-formatted string
List<Book> hits = searchSession.search( Book.class )
        .extension( ElasticsearchExtension.get() )
        .where( f -> f.matchAll() )
        .sort( f -> f.fromJson( "{"
                        + "\"title_sort\": \"asc\""
                + "}" ) )
        .fetchHits( 20 );


No comments:

Post a Comment