Can we override an index definition?

Hi everyone,

I’ve got a use where I need to override an index definition. The interface :

public interface ISearchableEntity {

    default String getTypeLabel() {
        return null;
    }
}

First class :

public class Acte implements ISearchableEntity {
@Transient
@FullTextField(name = TYPE_LABEL, analyzer = "standard", searchable = Searchable.YES)
    @KeywordField(name = TYPE_LABEL_SORT, sortable = Sortable.YES, aggregable = Aggregable.YES)
    @IndexingDependency(
            derivedFrom = {
                    @ObjectPath({@PropertyValue(propertyName = Acte_.TYPE_ACTE)})
            }
    )
    @Override
    public String getTypeLabel() {
        return getTypeActe() != null ? getTypeActe().getLibelle() : null;
    }

}

Second (child) class :

public class ActePrive extends Acte {

@Transient
    @FullTextField(name = TYPE_LABEL, analyzer = EDGE_NGRAM_2_15, searchAnalyzer = CUSTOM, searchable = Searchable.YES, projectable = Projectable.YES)
    @KeywordField(name = TYPE_LABEL_SORT, sortable = Sortable.YES)
    @IndexingDependency(
            derivedFrom = {
                    @ObjectPath({@PropertyValue(propertyName = ActePrive_.ACTE_DISTANT)})
            })
    @Override
    public String getTypeLabel() {
        String searchLabel = "AAE";
        if (Boolean.TRUE.equals(getActeDistant())) {
            searchLabel = "AAE à distance - Instrumentaire";
        }

        return searchLabel;
    }

}

As you can see, the definition is not the same, also for @IndexingDependency. But I can’t mass index code like this because the index names TYPE_LABEL and TYPE_LABEL_SORT are duplicated (which is forbidden)

You can override @IndexingDependency.

You can override the implementation of getTypeLabel().

But no, you cannot override the field definition. At least not when using annotation mapping.

In your case, that would lead to problems when searching, because when searching the Acte entity (thus both Acte instances and ActePrive instances), you would end up targeting two indexes that have different analyzers for the TYPE_LABEL field: which one would Hibernate Search pick, then?

The solution would be either:

  1. To pick a configuration that works for both types, and define the field in Acte only. E.g. remove @FullTextField / KeywordField in ActePrive, and in Acte, for TYPE_LABEL, use the analyzer EDGE_NGRAM_2_15 and make the fied projectable.
  2. To use different field names in Acte and ActePrive.

That being said… if you had a use case for different field definitions in a subclass, but somehow that field definition stayed compatible with the one of the superclass (e.g., simply enabling projections for subclasses, but not superclasses, without changing the analyzer), then technically that would be possible, just not with annotations.

You should be able to achieve that by defining the field through a TypeBinder instead of annotations, using conditions that check the mapped type with context.bridgedElement().isAssignableTo(ActePrive.class).

However, I’d advise against this solution if you can do otherwise: bridges are rather complex, and mapping a subtype differently from its supertype can lead to awkward situations.

Thank you for your complete answer. But the first line was sufficient. Thank you.