Ability to customize the written document (Elasticsearch)

How would I go about customizing the document that Hibernate Search ultimately writes?

I need to use the Percolate feature of Elasticsearch to identify documents in my search index. Probably best to read the Elasticsearch documentation to understand how this works. In my case, this means that I need a few things.

  1. Additional entries in the index mapping. One for a field of type “percolator” that contains the query and one to contain the mapping information of the virtual document to be created during the query execution.
  2. The ability to supply a value for the field of type “percolator” in the documents that get written to the index
  3. A means of executing the percolate query

In my case, since I am not using the index management features of Hibernate Search, I am able to create my own index mappings so item 1 is not an issue for me. Also, because I am trying to use Elasticsearch as natively in my code as possible, I am not using Hibernate Search query building and instead am writing the native Elasticsearch queries in my codebase, so item 3 is not an issue for me.

However, I have not found a solution for item 2 in that I have not found a way to customize the document Hibernate Search creates when writing the document to Elasticsearch. One thing I thought about doing was adding properties to my entity but wasn’t sure how to keep those properties from being persisted to my relational database while still having them be written to Elasticsearch. Also, for my case, the value of the percolate field is calculated depending on values of other properties of the entity and how it is calculated is based on the entity type.

Ideally i would like to be able to supply a means on a per entity basis that would allow me to manipulate the document that is written to Elasticsearch and not sure if this is possible.

I am using the Hibernate Search 6.0 Beta

I have been looking into Bridges but it is not yet clear to me if this can be used at the entity level and
to add fields to a document that are not persisted in the relational database.

This is exactly what you need.

The TypeBridge can be applied to a type and use multiple properties of that type.

You can access properties and combine them in the TypeBridge.write method. Then, in the same method, you can write the result of your computations to an index field.

You cannot manipulate the whole document, but you can add index fields whose content you fully define as JSON.

For Elasticsearch, you can declare index fields as “native”, giving you the ability to define their mapping as JSON directly and to write their value as JSON upon indexing. Documentation is coming in Beta3, but here is an example for Beta1/2. Just adapt the example to target types (annotation target, TypeBridge/TypeBinder instead of PropertyBridge/PropertyBinder) and to use the percolator index field type, and you should be good to go.

If you mean information that is completely transient and not stored in the database at all, such as a session ID from the HTTP request that changed the entity, then I wouldn’t recommend that at all: it would mean that, upon reindexing, that information would be lost.

If you mean information that is not stored “as is” in the database, but can be derived from the information stored in the database (a sum of two properties in the same entity, something like that), then yes you can totally do that. That’s the point of TypeBridges, actually. The example in the documentation concatenates the first and last name to index the full name, but you can do something more complicated. Just remember to declare the dependencies to the properties you use in your binder (context.getDependencies().use( ... )), otherwise Hibernate Search will sometimes “forget” to reindex your entity.

Note that in Beta3, APIs are going to change a little, but migration should be easy enough (a few lines of code).

@yrodiere thank you for getting back to me. TypeBridge worked for my use case. I was able to add percolate queries to my documents using a TypeBridge. The documentation and example you referenced helped me get it working.

1 Like