Using Hibernate Search in SEAM 2.0 Application

I implemented hibernate search recently in a SEAM project I was working on. I wanted to use the excellent suggestion tag from the excedel library and I wanted to use an index rather than hitting the database for each of the searches. I also wanted to use wildcard searches and for each keystroke this would be far to expensive. To implement it I completed the following steps: –

In my persistence.xml I added the following to the properties of my persistence-unit:-

<property name="hibernate.search.default.indexBase" value="PATH TO YOUR INDEX DIRECTORY"/>
<property name="hibernate.ejb.post-insert" value="org.hibernate.search.event.FullTextIndexEventListener"/>
<property name="hibernate.ejb.post-update" value="org.hibernate.search.event.FullTextIndexEventListener"/>
<property name="hibernate.ejb.post-delete" value="org.hibernate.search.event.FullTextIndexEventListener"/>

The path of your index base can be anywhere you want as long as the application has permission to write to it.

To used hibernate search you need to identify and highlight all of the classes that you want to search, you also need to identify each of the properties that you want indexed and the indexing strategy, you can find out what the various types are here Hibernate Search

@Indexed(index="index_direcory")
public class SomeClass

@Field(index=Index.TOKENIZED, analyzer = @Analyzer(impl = LowerCaseAnalyser.class))
@Column(name = "inv_name", length = 200, nullable = true)
private String name;

Inject an instance of FullTextEntityManager into your code. I used a stateless session bean that was used throughout the application

@In
private FullTextEntityManger entityManager;

I used a three different query types, RegEx, Prefix and WildCard.

RegexQuery(new Term(fieldName,".*[^-'\\w]" + searchString.toLowerCase() + "(\\s|$)"));
PrefixQuery(new Term(fieldName,searchString.toLowerCase()));
WildcardQuery(new Term(fieldName,'*'+searchString.toLowerCase()+'*'));

The regex one was used to search for firstname surname i.e. Jo Bloggs. The prefix query was used to search for Jo* i.e. Joanne, Jo Bloggs. The wildcard one, the most expensive one, was used to search for *Jo* i.e. Jones, BillyJoBloggs. The fieldname is the obviously the name of the field, so in:-

@Field(index=Index.TOKENIZED, analyzer = @Analyzer(impl = LowerCaseAnalyser.class))
private String name;  

FiledName would = name

All that is left to do it actually query the index and this is done by:

entityManager.createFullTextQuery(query,SomeClass.class).getResultList();

This has been in production for a some time now and it’s been stable and performed well. There has only been one instance to date of the index getting screwed up but I catered for that and enable the index to be rebuilt. I also had to provide this as any update to the indexed fields via direct sql wouldn’t be updated.

Advertisements