Feel like a geek and get yourself Ema Personal Wiki for Android and Windows

31 March 2009

Quickstart tutorial for NHibernate.Search

To use NHibernate.Search one has to extract the instructions from a lot of different places, which sometimes have outdated information. 
This blog post is a summary of how I was able to successfully add an NHibernate.Search-powered search function to an existing NHibernate project.

This guide assumes you have an NHibernate project and know how it works.

1. Assemblies
Add references to NHibernate.Search.dll and Lucene.Net.dll to your project. There is no official download for NHibernate.Search, you have to compile it yourself using the nhcontrib project. But you could also download the dll's I compiled on this site.

2. Configuration
Some properties have to be added to the Configuration object:
  
  'configure directory where indices are stored
  cnf.SetProperty("hibernate.search.default.directory_provider", _
    GetType(FSDirectoryProvider).AssemblyQualifiedName)
  cnf.SetProperty("hibernate.search.default.indexBase", "~/Index")
  cnf.SetProperty("hibernate.search.default.indexBase.create", "true")

  'event listeners to automagically update indices
  cnf.SetListener(NHibernate.Event.ListenerType.PostUpdate, _
    New FullTextIndexEventListener())
  cnf.SetListener(NHibernate.Event.ListenerType.PostInsert, _
    New FullTextIndexEventListener())
  cnf.SetListener(NHibernate.Event.ListenerType.PostDelete, _
    New FullTextIndexEventListener())

The direcotry where the indices are stored can be a relative path by using the ~ as the application root. This will be translated by NHibernate.Search to a real path.

3. Add search attributes to model 
  <Indexed(Index:="MyDomainClass")> _
as attribute on the class definition 

  <Field(Index.Tokenized, Store:=Store.No)> _
For searchable textfields 

  <DocumentId()> _
For the Id field.

4. Decorate the session 
Decorate the session with a full text searchable session:

Imports NHibernate.Search
[...]
session = Search.CreateFullTextSession(sessionFactory.OpenSession())

5. Convert existing data 
Often you will want existing data to be searchable. This can be done by indexing the old data once. New entries and changes will automatically be merged with the existing indices.
Here is a generic method to index existing data.

   '''
    ''' create full text index for type T
    '''
    Public Sub CreateIndex(Of T)()
      'decorate the session
      Dim fullTextSession = _
        NHibernate.Search.Search.CreateFullTextSession(Session)
      Using trans = fullTextSession.BeginTransaction()
        Dim query = fullTextSession.CreateQuery( _
          String.Concat("from ", GetType(T).Name) _
        )
        For Each thing In query.List()
          fullTextSession.Index(thing)
        Next
        trans.Commit()
      End Using
    End Sub

6. Add search to your repository (or [some layer] )
Now you can search with nhibernate! Lucene has some powerful features, but the nhibernate search in its simplest form looks like this:

  Dim query = fullTextSession.CreateFullTextQuery(Of MyDomainClass)(  _
    "MyProperty:searchterm1 OR AnotherProperty:searchword2" _
  )
 Dim results = query.List(Of MyDomainClass)

I hope this helps.