Cagatay Civici’s Weblog

“Real power can’t be given, it must be taken”

Full Text Search with Hibernate Search

Posted by cagataycivici on March 6, 2007

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.

4 Responses to “Full Text Search with Hibernate Search”

  1. Lars Says:

    You could also check out Compass to do this

  2. Cagatay Says:

    Yes, we use compass jdbcdirectoryprovider to store the indexes in db. Anyway if filesystem will be used,I’d not like to have yet another dependency since this is already builtin feature of hibernate.

  3. Nina Andersen Says:

    I have an existing Spring + Hibernate web application. I haven’t used Hibernate Search (Lucene) before. I don’t want my index to reside on a local file directory. How can I configure the index (hibernate.search.default.indexDir) to be stored in the database instead?

  4. Stas Ostapenko Says:

    Hi !

    Thanks for this post. I’ve used Spring+Lucene integration and Hibernate DAO with some AOP stuff to implement full-text search. I guess my blog entry could be interesting for you Search with Spring Hibernate Lucene and Aspect Oriented Programming in action

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>