Can I ask why you have to do this in code rather than in configuration?
If you were to do the same in configuration, first you would need to add the following to your web.config:
<configuration>
...
<configSections>
...
<section name="nhs-configuration" type="NHibernate.Search.Cfg.ConfigurationSectionHandler, NHibernate.Search" requirePermission="false" />
</configSections>
<nhs-configuration xmlns='urn:nhs-configuration-1.0'>
<search-factory>
<property name="hibernate.search.default.directory_provider">NHibernate.Search.Store.FSDirectoryProvider, NHibernate.Search</property>
<property name="hibernate.search.default.indexBase">~\MySearchIndexFolder</property>
</search-factory>
</nhs-configuration>
</configuration>
The configuration above will create a search index in a folder called "MySearchIndexFolder" in the root of your web app. You will need to give Network Service read / write access to this folder.
Next you need to attribute your Entity that you are going to create a search index for:
using Lucene.Net.Analysis.Standard;
using NHibernate.Search.Attributes;
[Indexed(Index = "MyEntity")]
public class MyEntity : Entity
{
[DocumentId]
public new virtual int Id
{
get { return base.Id; }
protected set { base.Id = value; }
}
[Field(Index.Tokenized, Store = Store.Yes)]
[Analyzer(typeof(StandardAnalyzer))]
[DomainSignature]
public virtual string Name { get; set; }
[Field(Index.Tokenized, Store = Store.Yes)]
[Analyzer(typeof(StandardAnalyzer))]
[DomainSignature]
public virtual string Description { get; set; }
}
Then in you would create a new class called SearchRepository, which inherits from the S#arp Arch Repository<T>:
using global::NHibernate;
using global::NHibernate.Search;
using global::NHibernate.Search.Cfg;
using Lucene.Net.Analysis;
using Lucene.Net.Analysis.Standard;
using Lucene.Net.Index;
using Lucene.Net.QueryParsers;
using Lucene.Net.Search;
using Lucene.Net.Store;
using SharpArch.Data.NHibernate;
public class SearchRepository : Repository<MyEntity>
{
public void BuildSearchIndex()
{
FSDirectory directory = null;
IndexWriter writer = null;
Type type = typeof(MyEntity);
var info = new DirectoryInfo(this.GetIndexDirectory());
if (info.Exists)
{
info.Delete(true);
}
try
{
// Now recreate the index - NB the boolean flag
directory = FSDirectory.GetDirectory(Path.Combine(info.FullName, type.Name), true);
writer = new IndexWriter(directory, new StandardAnalyzer(), true);
}
finally
{
if (directory != null)
{
directory.Close();
}
if (writer != null)
{
writer.Close();
}
}
IFullTextSession fullTextSession = Search.CreateFullTextSession(this.Session);
// select all MyEntity objects from NHibernate and add them to the Lucene index
foreach (MyEntity instance in Session.CreateCriteria(typeof(MyEntity)).List<MyEntity>())
{
fullTextSession.Index(instance);
}
}
public IList<MyEntity> DoSearch(string term)
{
var parser = new MultiFieldQueryParser(new[] { "Description" }, new StandardAnalyzer());
Query query = parser.Parse(term);
IFullTextSession session = Search.CreateFullTextSession(this.Session);
IQuery fullTextQuery = session.CreateFullTextQuery(query, new[] {typeof(MyEntity)});
IList<MyEntity> results = fullTextQuery.List<MyEntity>();
return results;
}
private string GetIndexDirectory()
{
INHSConfigCollection nhsConfigCollection = CfgHelper.LoadConfiguration();
string property = nhsConfigCollection.DefaultConfiguration.Properties["hibernate.search.default.indexBase"];
var fi = new FileInfo(property);
return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fi.Name);
}
}
Next you will need to execute BuildSearchIndex() - as this process runs in IIS you will need to use Task Manager to monitor the W3WP.exe worker process - it will consume CPU until it has finished building the index. It could take some time.
Once the index has built, you can use the tool Luke -
http://www.getopt.org/luke/ - to examine the index (file > open index > navigate to MySearchIndexFolder\MyEntity). This will display the contents of the and the words that have been extracted / analyzed from the "Description" field. You can also test your Lucene Queries in this tool. Its very useful and I suggest you read more about it.
Then you should be able to call DoSearch() and return a collection of matching MyEntity objects that contain the specified word in the Description field.
I have this working against the latest version of S#arp Arch. All it is dependent on is the Repository<T> class.
I hope this helps,
/Howard