Full Text Search with Hibernate Search

Doing Full Text Search in your domain model might be tricky in the past but now with Hibernate Search based on Lucene it’s not a problem. If you’re already using hibernate annotations, configuration is very easy and can be done in a few steps. Firstly annotating the domain model with a few simple annotations and then adding the hibernate event listeners to the hibernate configuration sets up the whole thing. In our project with my teammate Sylvain Vieujot(co-author of Hibernate Search along with Emmanuel Bernard) we’ve integrated full text search to our forum module. Here’s a simplified example;

Configuration
By default lucene indexes are can be saved either on file system or in memory. This can be configured by the “hibernate.search.default.directory_provider” parameter. Instead of these directory providers, it’s possible to hold the indexes in database using the Compass’s extension called JDBCDirectoryProvider. In addition a couple of event listeners need to be configured.

hibernate.search.default.directory_provider=org.hibernate.search.store.FSDirectoryProvider
hibernate.search.default.indexDir=C:\LuceneIndexes

 hibernate-configuration>
    …
    …
    …
    <event type=”post-update”
        <listener class=”org.hibernate.search.event.FullTextIndexEventListener”/>
    </event>
    <event type=”post-insert”
        <listener class=”org.hibernate.search.event.FullTextIndexEventListener”/>
    </event>
    <event type=”post-delete”
        <listener class=”org.hibernate.search.event.FullTextIndexEventListener”/>
    </event>
    …
    …
    …
</hibernate-configuration>

Domain Model
The annotations are the glue to the lucene. Field, Index, Store, Boost they all refer to the core lucene api. By use of these hibernate search takes care of the underlying lucene search engine configuration.

  
    
    

@Entity
@Indexed
public class ForumPost implements Serializable{

  private Long id;
  private String subject;
  private String message;
  
  @Id
  @DocumentId
  public Long getId() {
    return id;
  }
  public void setId(Long id) {
    this.id = id;
  }
  
  @Field(index=Index.TOKENIZED)
  public String getSubject() {
    return subject;
  }
  public void setSubject(String subject) {
    this.subject = subject;
  }
  
  @Field(index=Index.TOKENIZED, store=Store.YES)
  public String getMessage() {
    return message;
  }
  public void setMessage(String message) {
    this.message = message;
  }
}
      

Query
The coolest thing here is that, a lucene Query becomes a hibernate Query and you can use the regular stuff like list, scroll with it. In the example below Lucene Query Api is used, but it’s also possible to use Lucene’s Query Parser too, it does not matter since both can create a Lucene Query Object.

  
    
    

    public List searchByKeyword(String keyword) {
    BooleanQuery booleanQuery = new BooleanQuery();
    booleanQuery.addnew PrefixQuerynew Term"subject", keyword ) ), BooleanClause.Occur.SHOULD );
    booleanQuery.addnew PrefixQuerynew Term"message", keyword ) ), BooleanClause.Occur.SHOULD );
    org.hibernate.Query fullTextQuery = getFullTextSession().createFullTextQuery(booleanQuery, ForumPost.class);
    List result = fullTextQuery.list();
}

  public FullTextSession getFullTextSession() {
    Session session = sessionFactory.openSession();
    FullTextSession fullTextSession = Search.createFullTextSession(session);
    return fullTextSession;
}
      

When the session factory is built, empty lucene directories per entity is created under the main lucene index. Using FullTextSession.index(Object entity) method, it’s possible to rebuild an index of an entity. With the Luke tool, you can browse the lucene indexes kept in filesystem, this’ll really help during development.

One Response to Full Text Search with Hibernate Search

  1. Neil says:

    Does JDBCDirectoryProvider regenerate the indexes any time an indexed field is updated. For example, if someone bypasses the entity manager or Hibernate session and updates the database directly using SQL in SQL Plus, will the indexes be updated automatically?

    If not, what are the options under such a scenario?

    Thanks.

%d bloggers like this: