找回密码
 立即注册
首页 业界区 业界 NHibernate.Search 基于Lucene.NET的全文索引

NHibernate.Search 基于Lucene.NET的全文索引

步雪卉 2025-5-30 01:21:54
      NHibernate.Search现在是NHiberante Contrilb下面的一个还没有发布的项目,也是从Hibernate.Search移植而来,把NHibernate和Lucene.NET结合在一起,ORM持久化对象到数据库中,Lucene.NET提供索引及查询支持.
     下面在实际使用一下NHibernate.Search的使用:     
     由于这个项目还没有发布,它的很多特性也是一直在变化,所以现在只是以我下载的版本为准,如果你想尝试此项目,请下载最下面的代码,里面包括自己编译生成的NHibernate.Search及最新的Lucene.net相关的dll.     
   
一.配置     
    1.修改你的NHibernate配置信息的地方,同样添加NHibernate.Search的配置信息.
  1. <configSections>
  2. <section name="hibernate-configuration" type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate"/>
  3. <section name="nhs-configuration" type="NHibernate.Search.Cfg.ConfigurationSectionHandler, NHibernate.Search" <br>requirePermission="false" />
  4. <sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, <br>System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
  5. .....
  6. </configSections>
复制代码
        需要注意的是,在NHibernate.Search之前的版本中,曾经NHibernate.Search的配置信息和NHIbernate的放在一起.接下来,我们来看下具体的配置块:
  1. <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
  2.         <bytecode-provider type="lcg"/>
  3.         <reflection-optimizer use="true"/>
  4.         <session-factory name="NHibernateSearch.Demo">
  5.             <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider, NHibernate</property>
  6.             <property name="connection.connection_string">
  7.                 Data Source=|DataDirectory|Demo.db3;Version=3;Compress=False;synchronous=OFF;
  8.             </property>
  9.             <property name="show_sql">true</property>
  10.             <property name="dialect">NHibernate.Dialect.SQLiteDialect</property>
  11.             <property name="connection.driver_class">NHibernate.Driver.SQLite20Driver</property>
  12.             <property name="prepare_sql">true</property>
  13.             <property name="cache.provider_class">NHibernate.Cache.HashtableCacheProvider, NHibernate</property>
  14.             <property name="cache.use_query_cache">true</property>
  15.             <mapping assembly="NHibernateSearch.Demo.Model"/>
  16.         </session-factory>
  17.     </hibernate-configuration>
  18. <nhs-configuration xmlns='urn:nhs-configuration-1.0'>
  19.         <search-factory  sessionFactoryName="NHibernateSearch.Demo">
  20.             <property name='hibernate.search.default.directory_provider'>NHibernate.Search.Store.FSDirectoryProvider, <br>NHibernate.Search</property>
  21.             <property name='hibernate.search.default.indexBase'>~/Index</property>
  22.             <property name='hibernate.search.default.indexBase.create'>true</property>
  23.         </search-factory>
  24.     </nhs-configuration>
复制代码
     上面的是NHibernate的配置信息,由于我在示例程序中使用的是SQLite数据库,所以这个Demo也是一个SQLite+NHibernate的案例,而且里注意SQLite的连接字符串Data Source=|DataDirectory|Demo.db3,这样的话,只要把数据文件放在App_Data下面就可以运行了,而不用再去填写数据库文件的绝对路径.
     下面是NHibernate.Search的配置,我们采用基于文件目录的全文检索,索引文件放在根目录下面的Index文件夹下面.   
     另外,我们设置一下NHibernate的事件监听(如果不我们设置的话,我们要手动去调用,才能够使NHibernate在持久化对象时,同时处理全文索引),现在这个事件配置还不支持直接在NHibernate这样配置:
  1.   <br>       <listener class='NHibernate.Search.Event.FullTextIndexEventListener, NHibernate.Search' type='post-insert'/>
  2.   <br>       <listener class='NHibernate.Search.Event.FullTextIndexEventListener, NHibernate.Search' type='post-update'/>
  3.   <br>      <listener class='NHibernate.Search.Event.FullTextIndexEventListener, NHibernate.Search' type='post-delete'/>
复制代码
      现在我们只能在创建SessionFactory前,手动添加这个配置信息:
 
  1.                Configuration configuration = new Configuration();
  2.                 configuration.SetListener(NHibernate.Event.ListenerType.PostUpdate, new FullTextIndexEventListener());
  3.                 configuration.SetListener(NHibernate.Event.ListenerType.PostInsert, new FullTextIndexEventListener());
  4.                 configuration.SetListener(NHibernate.Event.ListenerType.PostDelete, new FullTextIndexEventListener());
  5.                 configuration.Configure();
  6.                 sessionFactory=  configuration.BuildSessionFactory();
复制代码
      我们为更新,删除,添加都配置了全文索引的事件监听,这样就能够保证索引文件里的数据和实际数据库里的保持一致,不要担心,这的性能也有考虑,这里可以支持最大提交数量,而不一定非要每条操作都去更改索引文件.
二.使用   
      首先我们要在NHibernate实体对象这里添加一些NHibernate.Search的一些关于全文索引的属性声明.不知道这里以后会不会支持xml的配置而不是修改原来的对象代码.
  1.     [Indexed(Index = "Book")]
  2.     public class Book
  3.     {
  4.         [DocumentId]
  5.         public  virtual string BookID
  6.         {
  7.             get;
  8.             set;
  9.         }
  10.         [Field(Index.Tokenized, Store = Store.Yes)]
  11.         public virtual string Title
  12.         {
  13.             get;
  14.             set;
  15.         }
  16.         [Field(Index.Tokenized, Store = Store.Yes)]
  17.         public virtual string Authors
  18.         {
  19.             get;
  20.             set;
  21.         }
  22.         [Field(Index.Tokenized, Store = Store.Yes)]
  23.         public virtual string Publisher
  24.         {
  25.             get;
  26.             set;
  27.         }
  28.         [Field(Index.Tokenized, Store = Store.Yes)]
  29.         public virtual string Summary
  30.         {
  31.             get;
  32.             set;
  33.         }
  34.     }
复制代码
     用过Lucene.Net的朋友们可能会发现,其实这些标识,原来在不使用NHibernate时是直接针对字段的.而现在只是针对一个业务对象的属性.这样的话,但数据添加或者更改时,就会自动的进行索引,但数据进行删除时,也自动更新索引,而可以不进行人为的干预.
    上面是一个对象Book,其中包含名称,作者,出版社,简介.我们要想实现对这几个属性进行全文检索的话,以前只能够同时拼几个LiKE,如果针对数据库,数据库数据的话肯定性能不会好,但是如果针对索引文件就不一样了.首先我们看一下怎么来实现搜索:   
    
  1. public   static IList<BookSearchResult>  FindBooks(string query)
  2.         {
  3.             IList<BookSearchResult> results = new List<BookSearchResult>();
  4.             Analyzer analyzer = new Lucene.Net.Analysis.Standard.StandardAnalyzer();
  5.    MultiFieldQueryParser parser = new MultiFieldQueryParser(new string[] { "Title", "Summary", "Authors", "Publisher"<br>    },         analyzer);
  6.             Query queryObj;
  7.             try
  8.             {
  9.                 queryObj = parser.Parse(query);
  10.             }
  11.             catch (ParseException)
  12.             {
  13.                 return results;
  14.             }
  15.             IFullTextSession session = Search.CreateFullTextSession(NHibernateHelper.GetCurrentSession());
  16.             <br>            ///1
  17.             System.Type targetType = typeof(Book);
  18.             IQuery nhQuery = session.CreateFullTextQuery(queryObj, new Type[] { targetType });
  19.             IList<Book> books = nhQuery.List<Book>();
  20.             NHibernate.Cfg.Configuration  cf =  new Configuration().Configure();
  21.             SearchFactoryImpl searchFactory   = SearchFactoryImpl.GetSearchFactory(cf);
  22.             IDirectoryProvider provider = searchFactory.GetDirectoryProviders(targetType)[0];
  23.             Workspace workspace = new Workspace(searchFactory);
  24.             IndexReader indexReader = workspace.GetIndexReader(provider, targetType);
  25.             Query simplifiedQuery = queryObj.Rewrite(indexReader);
  26.             SimpleHTMLFormatter formatter = new SimpleHTMLFormatter("<b class='term'>", "</b>");
  27.             Highlighter hTitle = GetHighlighter(simplifiedQuery, formatter, "Title", 100);
  28.             Highlighter hSummary = GetHighlighter(simplifiedQuery, formatter, "Summary", 200);
  29.             Highlighter hAuthors = GetHighlighter(simplifiedQuery, formatter, "Authors", 100);
  30.             Highlighter hPublisher = GetHighlighter(simplifiedQuery, formatter, "Publisher", 100);
  31.             foreach (Book book in books)
  32.             {
  33.                 BookSearchResult result = new BookSearchResult(book);
  34.                 TokenStream tsTitle = analyzer.TokenStream("Title", new System.IO.StringReader(book.Title ?? string.Empty));
  35.                 result.HighlightedTitle = hTitle.GetBestFragment(tsTitle, book.Title);
  36. TokenStream tsAuthors = analyzer.TokenStream("Authors", new System.IO.StringReader(book.Authors ?? string.Empty));
  37.                 result.HighlightedAuthors = hAuthors.GetBestFragment(tsAuthors, book.Authors);
  38. TokenStream tsPublisher = analyzer.TokenStream("Publisher", new System.IO.StringReader(book.Publisher ??<br>                string.Empty));
  39.                 result.HighlightedPublisher = hPublisher.GetBestFragment(tsPublisher, book.Publisher);
  40. TokenStream tsSummary = analyzer.TokenStream("Summary", new System.IO.StringReader(book.Summary ?? <br>string.Empty));
  41. result.HighlightedSummary = hSummary.GetBestFragments(tsSummary, book.Summary, 3, " ... <br /><br /> ... ");
  42.                 results.Add(result);
  43.             }
  44.             return results;
  45.         }
复制代码
      相信使用过Lucene.Net的朋友对上面的代码并不难理解,所有使用IFullTextSession的操作,都会进行全文索引的处理.另外这里还有多字段解析和分词的技术,就不详细介绍了.上面还使用了对查询关键字进行高亮显示,其中的BookSearchResult实体也只是对Book进行了包装,进行了显示的一些处理.具体请查看源代码.
      你可以在上面注释的///1处,添加对Book的一些操作,就可以显示的查看索引文件是否也同时进行了更新了.   
二.结果   
     下载直接运行整个项目,输入”程序”关键字,你会发现,在很短时间内,列出来了符合的记录,并黑色显示匹配的字(至于与不进行索引的搜索性能对比,留给以后再做吧):   
  
1.jpeg

 
 
三.资料及参考   
    1.NHibernate.Search using Lucene.NET Full Text Index  http://blogs.intesoft.net/post/2008/03/NHibernateSearch-using-Lucene-NET-Full-Text-Index-Part1.aspx   
    2.NHibernate Search   http://darioquintana.com.ar/blogging/?p=21   
    3.Lucene.NET and NHibernate.Search on medium trust http://www.klopfenstein.net/lorenz.aspx/lucene-net-and-nhibernate-search-on-medium-trust   
    4.Using NHibernate.Search with ActiveRecord http://using.castleproject.org/display/AR/Using+NHibernate.Search+with+ActiveRecord
     本次项目文件下载(NHibernate+SQLite+Lucene.Net).(for Vs 2008)
 
作者:孤独侠客(似水流年)   
出处:http://lonely7345.cnblogs.com   
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册