Cannot apply sort (Version 5.x)

Hi,
I am getting this error:

Caused by: org.hibernate.search.exception.SearchException: HSEARCH000299: @SortableField declared on xxx.entities.warehouse.Article#articleLabel references to undeclared field 'articleLabel'

I annotated:

    @Transient
    @Translated
    @SortableField(forField = "articleLabel")
    var articleLabel: String = ""

Blockquote

and tried to apply sorting that way:

        val sort: Sort = qb
            .sort()
            .byField("articleLabel").andByScore() // Descending order
            .createSort()

Could you please tell me what’s wrong with my code?

You told Hibernate Search that the field articleLabel is sortable, but you did not declare the field articleLabel.

Add an @Field annotation.

    @Transient
    @Translated
    @Field
    @SortableField(forField = "articleLabel")
    var articleLabel: String = ""

If you stick to the property name for your field name, you can also remove forField = "articleLabel".

    @Transient
    @Translated
    @Field
    @SortableField
    var articleLabel: String = ""

OK, now it works,
but it does not sort as expected:
image

        val sort: Sort = qb
            .sort()
            .byField("articleLabel") // Descending order
            .createSort()

of course i applied the sort:

        val jpaQuery = fullTextEntityManager.createFullTextQuery(luceneQuery.createQuery(), Article::class.java)
            .setSort(sort)

I expected the results to be ordered alphabetically

You have to create a specific sort field that uses a specific analyzer configuration based on a keyword tokenizer (which does not separate tokens and keep your string as is) and potentially additional filters such as lowercase and ASCII folding.

If you’re using a field that is tokenized, you will have unexpected results.

1 Like

Right, sorry. My example above creates a field with the default analyzer, which will lead to weird results.

Try this:

    @Transient
    @Translated
    @Field(analyze = Analyze.NO)
    @SortableField(forField = "articleLabel")
    var articleLabel: String = ""

Then reindex, and try again. You’ll get a case-sensitive sort, which is a start but is not very nice.

To get case-insensitive sort, you will need a normalizer.

@Indexed
@NormalizerDef(name = "lowercase",
  filters = @TokenFilterDef(factory = LowerCaseFilterFactory.class))
public class MyEntity {
    // ...

    @Transient
    @Translated
    @Field
    @Field(name = "articleLabel_sort", analyze = Analyze.NO, normalizer = @Normalizer(definition = "lowercase"))
    @SortableField(forField = "articleLabel_sort")
    var articleLabel: String = ""

    // ...
}

Then reindex.

Then sort like this:

        val sort: Sort = qb
            .sort()
            .byField("articleLabel_sort")
            .createSort()

See here for more information about normalizers.

1 Like