NHibernate Search and Sharp

18 views
Skip to first unread message

tracelord

unread,
Apr 24, 2009, 1:28:28 AM4/24/09
to S#arp Architecture
Hi everyone,

I develop an application with Sharp Arch and try to use NHibernate
search but I can't because we need put code in a configure object.

Anyone can help me.

Thanks

Howard van Rooijen

unread,
Apr 24, 2009, 3:11:32 AM4/24/09
to sharp-arc...@googlegroups.com
Hi,

I’m currently working on integrating NHibernate.Search in to the S#arp Arch trunk.

What configuration problems are you having?

To Get NH.Search working in my app the only configuration I needed to add was to the NHibernate.config (and you only need this if you want to automatically propagate changes in your repository to your search index):

<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
   <session-factory>
     ...
      <listener class="NHibernate.Search.Event.FullTextIndexEventListener, NHibernate.Search" type="post-update"></listener>
      <listener class="NHibernate.Search.Event.FullTextIndexEventListener, NHibernate.Search" type="post-insert"></listener>
      <listener class="NHibernate.Search.Event.FullTextIndexEventListener, NHibernate.Search" type="post-delete"></listener>
   </session-factory>
</hibernate-configuration>

Have you sucessfully created your Search Index yet?

/Howard

tracelord

unread,
Apr 24, 2009, 2:44:53 PM4/24/09
to S#arp Architecture
Hi,

Thanks Howard.

I have one question, where put this code..??

cfg = new Configuration();
cfg.SetProperty("hibernate.search.default.directory_provider",
typeof(RAMDirectoryProvider).AssemblyQualifiedName);
cfg.SetProperty(NHibernate.Search.Environment.AnalyzerClass,
typeof(StopAnalyzer).AssemblyQualifiedName);
cfg.Configure();
sf = cfg.BuildSessionFactory();
SearchFactory.Initialize(cfg, sf);

Because I need this configuration for NHibernate Search works.

Could explain me more detail what need to do for NH Search work with
sharp and what version of sharp need, because actually I work with the
version 0.9.114.

Thanks in advanced.

Sorry for my poor english.

On 24 abr, 01:11, Howard van Rooijen <howard.vanrooi...@gmail.com>
wrote:
> Hi,
>
> I’m currently working on integrating NHibernate.Search in to the S#arp Arch
> trunk.
>
> What configuration problems are you having?
>
> To Get NH.Search working in my app the only configuration I needed to add
> was to the NHibernate.config (and you only need this if you want to
> automatically propagate changes in your repository to your search index):
>
> <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
>    <session-factory>
>      ...
>       <listener class="NHibernate.Search.Event.FullTextIndexEventListener,
> NHibernate.Search" type="post-update"></listener>
>       <listener class="NHibernate.Search.Event.FullTextIndexEventListener,
> NHibernate.Search" type="post-insert"></listener>
>       <listener class="NHibernate.Search.Event.FullTextIndexEventListener,
> NHibernate.Search" type="post-delete"></listener>
>    </session-factory>
> </hibernate-configuration>
>
> Have you sucessfully created your Search Index yet?
>
> /Howard
>

Howard van Rooijen

unread,
Apr 24, 2009, 5:33:00 PM4/24/09
to sharp-arc...@googlegroups.com
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

tracelord

unread,
Apr 25, 2009, 9:32:56 PM4/25/09
to S#arp Architecture
Hi Howard and thanks again,

I create all with your instructions, then create the index file and
create fine. But when I tried to see the file with Luke give me "Error
0".

Whe I ran the DoSearch function the unit test failed because don
retrive anything.

What I do wrong?

Thanks aganin for your help.



Howard van Rooijen ha escrito:
Reply all
Reply to author
Forward
0 new messages