Integer field taken as entity

Main entity is Article having list of PriceInfo which holds amount, currency and Provider entity.
Each Provider has a parent and list of children, but only one of those is filled giving me exactly two levels of parent-child relation.

Parent Provider is used for generic prices, for example large brands having many stores around the country. Child Provider is used for specific store in case when article is, for example, on discount in that particular store and not in all stores.

In order to display all Article entries under parent Provider including also those under child Provider I generated a bridge that creates parentId field inside Provider.


During creation of SearchPredicate childProvidersByParentId (line 9, code snippet is below) exception is thrown:

HSEARCH600050: Unable to convert DSL argument: Cannot cast java.lang.Integer to com.thevegcat.app.entities.provider.Provider

Is it possible to create Integer value and only Integer value instead of whole parent Provider because all other content from parent Provider is not relevant for search? What am I doing wrong?

Java Version: 18.0.2.1
Spring Boot version: 3.0.4
Hibernate version: 6.2.0.CR3
Hibernate Search version: 6.1.8.Final (afraid to put 6.2.0.Alpha2 into production)


Article.java

class Article {
    @IndexedEmbedded
    private Set<PriceInfo> priceInfos;
}

PriceInfo.java:

class PriceInfo {
    private BigDecimal amount;
    private CustomCurrency currency;

    @IndexedEmbedded
    private Provider provider;
}

Provider.java

class Provider {
    @GenericField(
        projectable = Projectable.NO,
        searchable = Searchable.YES,
        sortable = Sortable.NO
    )
    private Integer id;

    @GenericField(
        name = "parentId",
        projectable = Projectable.NO,
        searchable = Searchable.YES,
        sortable = Sortable.NO,
        valueBridge = @ValueBridgeRef(type = ProviderIdBridge.class)
    )
    private Provider parent;
}

ProviderIdBridge.java

class ProviderIdBridge implements ValueBridge<Provider, Integer> {
    @Override
    public Integer toIndexedValue(
        Provider provider,
        ValueBridgeToIndexedValueContext context
    ) {
        if (provider == null) {
            return null;
        }
        return provider.getId();
    }
}

Code snippet to generate SearchPredicate:

01  SearchPredicateFactory pf = searchSession.scope(Article.class).predicate();
02
03  SearchPredicate mainProviderById =
04     pf.match()
05         .field("priceInfos.provider.id")
06         .matching(providerId)
07         .toPredicate();
08 
09  SearchPredicate childProvidersByParentId =
10     pf.match()
11         .field("priceInfos.provider.parentId")
12         .matching(providerId)
13         .toPredicate();
14 
15   SearchPredicate all =
16     pf.bool()
17         .should(mainProviderById)
18         .should(childProvidersByParentId)
19         .minimumShouldMatchNumber(1)
20         .toPredicate();

Hey @horvoje,

Thanks for reaching out!

You’d want to check the alternative matching(..) method that accepts two parameters, with the second one being a ValueConvert enum. You can tell Hibernate Search not to apply the converter and pass the value as it is:

SearchPredicate childProvidersByParentId =
     pf.match()
         .field("priceInfos.provider.parentId")
         .matching(providerId, ValueConvert.NO)
         .toPredicate();

See also Example 279. Disabling the DSL converter in Type of arguments passed to the DSL

2 Likes

Thanks a million - tried it right now and it’s working!

2 Likes

Thanks Marko; just a few more things:

There’s also a section precisely about that in the documentation of the field predicate: Hibernate Search 6.2.2.Final: Reference Documentation

Also:

.minimumShouldMatchNumber(1) is unnecessary in this case, as it’s the default when you only have should clauses.

1 Like