Hello,
I am working on a project using Hibernate Search version 7.1.0 with an OpenSearch backend. I am looking to implement a feature that allows aggregating all fields from an entity into a single indexed field to enable efficient searching using the “english” analyzer. It’s crucial that this field not be added to the class annotated with @Entity
.
I implemented a custom ValueBridge
that aggregates data from various entity fields. Here is the implementation example:
public class GenericOrderValueBridge implements ValueBridge<GenericOrder, String> {
@Override
public String toIndexedValue(GenericOrder order, ValueBridgeToIndexedValueContext context) {
return Stream.of(
getFieldValues(order.getSample()),
getOrderFields(order),
getResultFields(order.getResult()),
getWorklistFields(order.getWorklist()),
getWorksheetFields(order.getWorksheet())
)
.flatMap(Stream::of)
.filter(Objects::nonNull)
.map(Object::toString)
.collect(Collectors.joining(" "));
}
private Object[] getFieldValues(Sample sample) {
return new Object[]{
sample.getId(),
sample.getDescription(),
sample.getProjectName()
};
}
private Object[] getOrderFields(Order order) {
return new Object[]{
order.getId(),
order.getCreatedAt(),
order.getDescription()
};
}
private Object[] getResultFields(Result result) {
return new Object[]{
result.getId(),
result.getStartDate(),
result.getEndDate()
};
}
private Object[] getWorklistFields(Worklist worklist) {
return new Object[]{
worklist.getId(),
worklist.getCreatedAt()
};
}
private Object[] getWorksheetFields(Worksheet worksheet) {
return new Object[]{
worksheet.getId(),
worksheet.getCreatedAt()
};
}
}
I added this value bridge to the mapping configuration as follows:
public void configure(HibernateOrmMappingConfigurationContext context) {
var mapping = context.programmaticMapping();
var typeMapping = mapping.type(GenericOrder.class);
typeMapping.indexed();
typeMapping.property("allFields")
.fullTextField()
.valueBridge(new GenericOrderValueBridge())
.analyzer("english");
}
However, during integration testing, I encountered a problem suggesting that Hibernate Search expects the field allFields
to exist in the GenericOrder
class, which is not my intention. Here is the exception:
Caused by: org.hibernate.search.util.common.SearchException: HSEARCH700078: No readable property named 'allFields' on type 'com.example.app.model.GenericOrder'.
at org.hibernate.search.mapper.pojo.model.spi.AbstractPojoRawTypeModel.property(AbstractPojoRawTypeModel.java:113)
at org.hibernate.search.mapper.pojo.mapping.definition.programmatic.impl.TypeMappingStepImpl.property(TypeMappingStepImpl.java:108)
at com.example.app.config.HibernateSearchConfig.genericOrderMapping(HibernateSearchConfig.java:158)
at com.example.app.config.HibernateSearchConfig.configure(HibernateSearchConfig.java:135)
... 73 more
Is there a way to define such a synthetic field in the Hibernate Search configuration that doesn’t exist directly in the database model but can be indexed and searched? What best practices or alternative approaches would you recommend?
Thank you in advance for any help.