Hibernate Search automatic update of composed fields

Florian Gutmann Source

I have a Person entity with multiple name related properties (firstName, lastName, title). All the name related properties should be stored in a single lucene index field "fullName".

@Indexed
@Entity
public class Person {
   ...
   private String firstName;
   private String lastName;
   private String title;

   @Field(store=Store.NO, index=Index.TOKENIZED)
   public String getFullName() {
      return firstName + " " + lastName + " " + title;
   }
}

The only problem I'm facing is to automatically update the fullName in the index when a name related property is updated.

Is there some way to tell Hibernate Search that fullName is a composed field and must be updated when one of the parts changes? Maybe something like this?

@ComposedOf({"firstName", "lastName", "title"})

Thank you!

lucenehibernate-search

Answers

answered 5 years ago Hardy #1

There are several solutions for your problem and it the solution you are choosing is probably a matter of taste (you might also apply a combination of them):

  1. Check the property _hibernate.search.‚Äčenable_dirty_check_ and make it sure it is set to false in your case. The default is true. See the online docs for more information - http://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/
  2. Add the @Field annotation also to firstName, lastName and title. You get a bigger index size, but often that does not matter. As a side effect the dirty checking will work (assuming btw that your JPA annotations are correct. For example I am assuming getFullName is transient)
  3. Use a class bridge and optionally remove getFullName. Using a class bridge will also automatically disable the dirty check optimisation

answered 5 years ago Sanne #2

@Indexed
@Entity
public class Person {
   ...
   @Field(name="fullName") String firstName;
   @Field(name="fullName") String lastName;
   @Field(name="fullName") String title;
}

This is possible as you have chosen TOKENIZED and I'm assuming your analyzer is set to split the tokens on whitespace as you're adding whitespace to separate them: you can have multiple repetitions of a same field, the result is almost the same as splitting the compound terms (I say almost as it won't be able to determine ordering of terms in case you need a PhraseQuery looking for a specific order of keywords).

For more complex cases you would use a ClassBridge which disables the dirty-checking optimisation which has been annoying you in this case: Hibernate Search tracks if any persistent field was actually written to to decide if it can skip expensive reindexing operations but is then unable to detect such tricks.

comments powered by Disqus