Ayende @ Rahien

My name is Oren Eini
Founder of Hibernating Rhinos LTD and RavenDB.
You can reach me by phone or email:


+972 52-548-6969

, @ Q c

Posts: 6,026 | Comments: 44,842

filter by tags archive

NHibernate Search

time to read 4 min | 605 words

NHibernate Search is an extension to NHibernate that allows you to utilize Lucene.NET, a full text search engine as your query engine, instead of putting additional load on the database itself. In a sense, this is a good way outsource your queries from the database.

This has several chief advantages:

  • Your database is now mostly about performing queries by primary key (fast) and handling data storage, transactional semantics, etc. All of which should be very fast.
  • Your costly queries can now run on a different (cheap) machine, and a long query isn’t going to take locks in the database (slowing everything down).
  • Lucene.NET is a document database, this means that some things are significantly cheaper to query than in an RDBMS

Using NHibernate Search is very easy, from configuration stand point, we need to define the following listeners:

<listener class='NHibernate.Search.Event.FullTextIndexEventListener, NHibernate.Search'
<listener class='NHibernate.Search.Event.FullTextIndexEventListener, NHibernate.Search'
<listener class='NHibernate.Search.Event.FullTextIndexEventListener, NHibernate.Search'

That done, we need to annotate our classes with attributes that will tell NHibernate Search how we want our entities to be indexed. Unlike NHibernate Validator, there is no alternate XML configuration for the indexing specification.

We annotate our entities like this:

public class Post
	public virtual int Id { get; set; }

	public virtual Blog Blog { get; set; }

	public virtual User User { get; set; }

	[Field(Index.Tokenized, Store = Store.Yes)]
	public virtual string Title { get; set; }

	public virtual string Text { get; set; }

	public virtual DateTime PostedAt { get; set; }

	public virtual ISet<Comment> Comments { get; set; }

	public virtual ISet<Category> Categories { get; set; }

	public virtual ISet<Tag> Tags { get; set; }

I am not going to go over the semantics of each attribute, and how they play together, suffice to say that Hibernate Search in Action will give you all the details about how to use this.

That said, let us look how this will actually get indexed:


We have a document, which has fields, and we can query those fields by any of its values, and get a pretty fast reply back. Note that the document structure that we have here is flat, so what would usually be a join is now an almost no cost operation. Of course, the more we put in the index, the bigger it is, but that is another tradeoff.

We can now query the index using:

using (var s = sf.OpenSession())
using(var search = Search.CreateFullTextSession(s))
using (var tx = s.BeginTransaction())
	var list = search.CreateFullTextQuery<Post>("Tags.Name:Hello")

	foreach (var post in list)


As I said, actually getting down into all the syntax, options and tricks that we can use here is beyond the scope of this post, that is why I pointed out the book, which cover all of them in depth.



this is absolute gold; only wish I had this about 2.5 years ago when working on a system with very heavy use of full-text searches. Would have saved us mountains of headaches.

Andreas &#214;hlund

Nice post!

What tool are you using to display the contents of the index?

Marco Parenzan

Is Lucene.NET currently supported? I've seen that Lucene was out with version 2.4.1 in March 2009, while Licene.NET have a 2.0 version from 2007. Is valid to use it?

Jozef Sevcik


NHibernate.Search project in trunk uses latest stable Lucene 2.0.

However, I can confirm NH.Search works well with Lucene.NET trunk version (marked as 2.3).

It only requires downloading Lucene.NET from their SVN, building and then building NHibernate.Search with Lucene.NET 2.3 dll.

Ayende Rahien


I can't speak about Lucene.NET catching up to Lucene, but Lucene.NET is most certainly supported by NHibernate Search

Paul Hatcher


We can upgrade to Lucene 2.4.1 quite easily - bear in mind that the project hadn't had a formal release for quite a while, we were using the latest.


Paul Hatcher

Sorry, mis-read the comment - the version of Lucene.NET we are using is almost up to date, we are using 2.31, they recently (March) changed over to 2.3.2 so I'll update to that in the next few days.




Is there any way to put those attributes dynamically? We have entities with various number of fields (configuration is built in the runtime using dynamic components) and thus we don't have explicit fields. Could you recommend something in this case?


I assume that DateTime fields can be indexed ? (missing in the code above)

Ayende Rahien


No, but feel free to submit a patch to do that.

Ayende Rahien


Yes they can be, but be aware that they are done using textual indexing, not value indexing

This means that the granularity that you use it important

Is it really possible to index the Categories like this, im trying to do exactly that but the items in the list wont get indexed in the file (checked with luke). In my case the ISet
<category is a many to many, could that cause the non existence of indexes?
Sebastijan Pistotnik

How do I index existing data? I am reading in Hibernate in action book about the fact that most of the time index data set cannot fit all in memory. If I attempt to load all objects and then index them, I can face OutOfMemoryException. So there is a method indexAllItems where in java it is used ScrollableResults and a method flushToIndexes on session object. What is the equivalent in .net for ScrollableResults and flushToIndexes. I checked the source code but there is no implementation for them. So is there some example how to do it?


Hi Ayende,

Could you point to some articles which talks about using threaded parallel indexing to create faster indexes. I am trying to index around 2 million records it takes around 10+hrs. The initial 100K-200K is fast then it slows down very much.


Ayende Rahien


Ping me on email so we can discuss this more easily, I would need to see the code for doing the indexes.


i'm wondering what is the recommended way of indexing a large quantity of existing data, so i' would be interested in this email thread :)

The examples most found on the net regarding Lucene.net integration with Nhibernate.Search deal mainly with automatic event wiring and inserting new data in the db, but i've yet to find an example for the other problem.

I haven't done a benchmark for IFullTextSession.Index yet, but i think this will be the simpler way of working in my case:

  • Page 1024 items

  • Index them

  • repeat t'il done

But i'm waiting for any other advice :)

Ayende Rahien


Yep, that is the way to go

Comment preview

Comments have been closed on this topic.


No future posts left, oh my!


  1. Technical observations from my wife (3):
    13 Nov 2015 - Production issues
  2. Production postmortem (13):
    13 Nov 2015 - The case of the “it is slow on that machine (only)”
  3. Speaking (5):
    09 Nov 2015 - Community talk in Kiev, Ukraine–What does it take to be a good developer
  4. Find the bug (5):
    11 Sep 2015 - The concurrent memory buster
  5. Buffer allocation strategies (3):
    09 Sep 2015 - Bad usage patterns
View all series


Main feed Feed Stats
Comments feed   Comments Feed Stats