Sorting Hibernate Search 6 results by custom sort (not score)

Previously in Hibernate Search 5 I had sort defined as constant. Later when issuing a search, it was applied to a query: fullTextQuery.setSort(sort);

private static final boolean REVERSE = true;
private static final boolean NATURAL = false;
private static final Sort ARTICLE_DEFAULT_SORT =
	new Sort(
		new SortField("importance_numeric", SortField.Type.INT, REVERSE),
		new SortField("completeness_level", SortField.Type.INT, REVERSE),
		SortField.FIELD_SCORE
		new SortField("sortableTitle", SortField.Type.STRING, NATURAL),
		new SortField("sortableManufacturer", SortField.Type.STRING, NATURAL)
	);

Now with Hibernate Search 6 I’m trying to do any kind of sort, but I have to admit - I’m lost.
The only thing I managed to write is:

org.hibernate.search.engine.search.query.SearchResult<T> searchResult =
	        searchSession
	        	.search(clazz)
				.where(searchPredicate)
				.sort(f ->
					f.field("sortableTitle")
						.then().field("sortableManufacturer")
				)
				.fetch(offset, limit);

Where clazz is a parameter declared as Class<T> clazz to have generic search service.

Is there any chance to create some sort supplier that will create sort depending on clazz and other additional parameters (for example one type of sort for homepage and other type of sort for search results).

Interfaces and classes SearchSort, SearchSortFactory, LuceneUserProvidedLuceneSortFieldSort, LuceneSearchIndexScope, LuceneUserProvidedLuceneSortSort are not well documented and there are no examples and the only thing I could do is to try to dig deep into code, but it will take too much time.

I would like to manage it as more in Hibernate Search 6 style as possible which means I want to avoid helpers that would use old code (LuceneSearchSortBuilderFactory.fromLuceneSort( OLD_SORT_HERE )).

Please help!

Internal code is not documented, that’s for sure. The javadoc of SearchSort and SearchSortFactory, as for all API classes, is the bare minimum required to guide someone who read about the basics in the reference documentation, e.g. here for sorts. It is not intended to replace the reference documentation.

Also, for migration, refer to the migration guide, in particular here for sorts.

The reference documentation, and to a lesser extent the migration guide, include the examples you’re requesting.

1 Like

While reading documentation I simply missed the example where SearchSort object is created over SearchScope object without lambdas. I should have read it more carefully, I know. But my battery is low after so many days just converting old stuff to new stuff not seeing/having anything in working condition.

Today I finally got first result from Hibernate Search 6 and also did a fine tune to get the same result order as with previous Hibernate Search 5. Here in Croatia we’ll say My happiness never ends!

Also search by “this” and “not” is now finally working which was actually my trigger to upgrade to Hibernate Search 6 because Hibernate Search 5 filtered it out no matter what stop words file says. :rofl:

1 Like

This one is for others - if sometimes someone comes here trying to figure out how to sort without lambdas:


Imports:

import org.hibernate.search.mapper.orm.session.SearchSession;
import org.hibernate.search.mapper.orm.Search;
import org.hibernate.search.mapper.orm.scope.SearchScope;
import org.hibernate.search.engine.search.sort.SearchSort;
import org.hibernate.search.engine.search.query.SearchQuery;
import org.hibernate.search.engine.search.query.SearchResult;

The search:

// assuming `jakarta.persistence.EntityManager` is available
// as injected bean `this.entityManager`

final SearchSession searchSession = Search.session(this.entityManager);

final SearchScope<Article> scope = searchSession.scope(Article.class);

final SearchSort sort =
	scope.sort()
		.field("importanceNumeric").desc().then()
		.field("sortableTitle").asc()
		.toSort();

final SearchQuery<Article> q =
	searchSession.search(scope)
		.where(searchPredicate)
		.sort(sort)
		.toQuery();

final SearchResult<Article> searchResult = q.fetch(offset, limit);

final List<Article> hits = searchResult.hits();