NHibernate.Search現在是NHiberante Contrilb下面的一個還沒有發布的項目,也是從 Hibernate.Search移植而來,把NHibernate和Lucene.NET結合在一起,ORM持久化對象到數據庫 中,Lucene.NET提供索引及查詢支持.
下面在實際使用一下NHibernate.Search的使用:
由於這個項目還沒有發布,它的很多特性也是一直在變化,所以現在只是以我下載的版本為准,如果你想 嘗試此項目,請下載最下面的代碼,裡面包括自己編譯生成的NHibernate.Search及最新的Lucene.net相關 的dll.
一.配置
1.修改你的NHibernate配置信息的地方,同樣添加NHibernate.Search的配置信息.
<configSections>
<section name="hibernate-configuration" type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate"/>
<section name="nhs-configuration" type="NHibernate.Search.Cfg.ConfigurationSectionHandler, NHibernate.Search"
requirePermission="false" />
<sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup,
System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
.....
</configSections>
需要注意的是,在NHibernate.Search之前的版本中,曾經NHibernate.Search的配置信息和NHIbernate 的放在一起.接下來,我們來看下具體的配置塊:
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<bytecode-provider type="lcg"/>
<reflection-optimizer use="true"/>
<session-factory name="NHibernateSearch.Demo">
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider, NHibernate</property>
<property name="connection.connection_string">
Data Source=|DataDirectory|Demo.db3;Version=3;Compress=False;synchronous=OFF;
</property>
<property name="show_sql">true</property>
<property name="dialect">NHibernate.Dialect.SQLiteDialect</property>
<property name="connection.driver_class">NHibernate.Driver.SQLite20Driver</property>
<property name="prepare_sql">true</property>
<property name="cache.provider_class">NHibernate.Cache.HashtableCacheProvider, NHibernate</property>
<property name="cache.use_query_cache">true</property>
<mapping assembly="NHibernateSearch.Demo.Model"/>
</session-factory>
</hibernate-configuration>
<nhs-configuration xmlns='urn:nhs-configuration- 1.0'>
<search-factory sessionFactoryName="NHibernateSearch.Demo">
<property name='hibernate.search.default.directory_provider'>NHibernate.Search.Store.FSDirectoryPro vider,
NHibernate.Search</property>
<property name='hibernate.search.default.indexBase'>~/Index</property>
<property name='hibernate.search.default.indexBase.create'>true</property>
</search-factory>
</nhs-configuration>
上面的是NHibernate的配置信息,由於我在示例程序中使用的是SQLite數據庫,所以這個Demo也是一個 SQLite+NHibernate的案例,而且裡注意SQLite的連接字符串Data Source=|DataDirectory|Demo.db3,這樣 的話,只要把數據文件放在App_Data下面就可以運行了,而不用再去填寫數據庫文件的絕對路徑.
下面是NHibernate.Search的配置,我們采用基於文件目錄的全文檢索,索引文件放在根目錄下面的 Index文件夾下面.
另外,我們設置一下NHibernate的事件監聽(如果不我們設置的話,我們要手動去調用,才能夠使 NHibernate在持久化對象時,同時處理全文索引),現在這個事件配置還不支持直接在NHibernate這樣配 置:
<listener class='NHibernate.Search.Event.FullTextIndexEventListener, NHibernate.Search' type='post-insert'/>
<listener class='NHibernate.Search.Event.FullTextIndexEventListener, NHibernate.Search' type='post- update'/>
<listener class='NHibernate.Search.Event.FullTextIndexEventListener, NHibernate.Search' type='post- delete'/>
現在我們只能在創建SessionFactory前,手動添加這個配置信息:
Configuration configuration = new Configuration();
configuration.SetListener(NHibernate.Event.ListenerType.PostUpdate, new FullTextIndexEventListener());
configuration.SetListener (NHibernate.Event.ListenerType.PostInsert, new FullTextIndexEventListener());
configuration.SetListener(NHibernate.Event.ListenerType.PostDelete, new FullTextIndexEventListener());
configuration.Configure();
sessionFactory= configuration.BuildSessionFactory();
我們為更新,刪除,添加都配置了全文索引的事件監聽,這樣就能夠保證索引文件裡的數據和實際數據庫 裡的保持一致,不要擔心,這的性能也有考慮,這裡可以支持最大提交數量,而不一定非要每條操作都去更改 索引文件.
二.使用
首先我們要在NHibernate實體對象這裡添加一些NHibernate.Search的一些關於全文索引的屬性聲明. 不知道這裡以後會不會支持xml的配置而不是修改原來的對象代碼.
[Indexed(Index = "Book")]
public class Book
{
[DocumentId]
public virtual string BookID
{
get;
set;
}
[Field(Index.Tokenized, Store = Store.Yes)]
public virtual string Title
{
get;
set;
}
[Field(Index.Tokenized, Store = Store.Yes)]
public virtual string Authors
{
get;
set;
}
[Field(Index.Tokenized, Store = Store.Yes)]
public virtual string Publisher
{
get;
set;
}
[Field(Index.Tokenized, Store = Store.Yes)]
public virtual string Summary
{
get;
set;
}
}
用過Lucene.Net的朋友們可能會發現,其實這些標識,原來在不使用NHibernate時是直接針對字段的.而 現在只是針對一個業務對象的屬性.這樣的話,但數據添加或者更改時,就會自動的進行索引,但數據進行刪 除時,也自動更新索引,而可以不進行人為的干預.
上面是一個對象Book,其中包含名稱,作者,出版社,簡介.我們要想實現對這幾個屬性進行全文檢索的話 ,以前只能夠同時拼幾個LiKE,如果針對數據庫,數據庫數據的話肯定性能不會好,但是如果針對索引文件就 不一樣了.首先我們看一下怎麼來實現搜索:
public static IList<BookSearchResult> FindBooks(string query)
{
IList<BookSearchResult> results = new List<BookSearchResult>();
Analyzer analyzer = new Lucene.Net.Analysis.Standard.StandardAnalyzer();
MultiFieldQueryParser parser = new MultiFieldQueryParser(new string[] { "Title", "Summary", "Authors", "Publisher"
}, analyzer);
Query queryObj;
try
{
queryObj = parser.Parse(query);
}
catch (ParseException)
{
return results;
}
IFullTextSession session = Search.CreateFullTextSession(NHibernateHelper.GetCurrentSession());
///1
System.Type targetType = typeof(Book);
IQuery nhQuery = session.CreateFullTextQuery(queryObj, new Type[] { targetType });
IList<Book> books = nhQuery.List<Book>();
NHibernate.Cfg.Configuration cf = new Configuration().Configure();
SearchFactoryImpl searchFactory = SearchFactoryImpl.GetSearchFactory(cf);
IDirectoryProvider provider = searchFactory.GetDirectoryProviders(targetType) [0];
Workspace workspace = new Workspace(searchFactory);
IndexReader indexReader = workspace.GetIndexReader(provider, targetType);
Query simplifiedQuery = queryObj.Rewrite(indexReader);
SimpleHTMLFormatter formatter = new SimpleHTMLFormatter("<b class='term'>", "</b>");
Highlighter hTitle = GetHighlighter(simplifiedQuery, formatter, "Title", 100);
Highlighter hSummary = GetHighlighter (simplifiedQuery, formatter, "Summary", 200);
Highlighter hAuthors = GetHighlighter(simplifiedQuery, formatter, "Authors", 100);
Highlighter hPublisher = GetHighlighter(simplifiedQuery, formatter, "Publisher", 100);
foreach (Book book in books)
{
BookSearchResult result = new BookSearchResult(book);
TokenStream tsTitle = analyzer.TokenStream("Title", new System.IO.StringReader(book.Title ?? string.Empty));
result.HighlightedTitle = hTitle.GetBestFragment (tsTitle, book.Title);
TokenStream tsAuthors = analyzer.TokenStream("Authors", new System.IO.StringReader(book.Authors ?? string.Empty));
result.HighlightedAuthors = hAuthors.GetBestFragment(tsAuthors, book.Authors);
TokenStream tsPublisher = analyzer.TokenStream("Publisher", new System.IO.StringReader (book.Publisher ??
string.Empty));
result.HighlightedPublisher = hPublisher.GetBestFragment(tsPublisher, book.Publisher);
TokenStream tsSummary = analyzer.TokenStream("Summary", new System.IO.StringReader(book.Summary ??
string.Empty));
result.HighlightedSummary = hSummary.GetBestFragments(tsSummary, book.Summary, 3, " ... <br /><br /> ... ");
results.Add(result);
}
return results;
}
相信使用過Lucene.Net的朋友對上面的代碼並不難理解,所有使用IFullTextSession的操作,都會進行 全文索引的處理.另外這裡還有多字段解析和分詞的技術,就不詳細介紹了.上面還使用了對查詢關鍵字進 行高亮顯示,其中的BookSearchResult實體也只是對Book進行了包裝,進行了顯示的一些處理.具體請查看 源代碼.
你可以在上面注釋的///1處,添加對Book的一些操作,就可以顯示的查看索引文件是否也同時進行了更 新了.
二.結果
下載直接運行整個項目,輸入”程序”關鍵字,你會發現,在很短時間內,列出來了符合的記錄,並黑色顯 示匹配的字(至於與不進行索引的搜索性能對比,留給以後再做吧):
三.資料及參考
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
出處:http://lonely7345.cnblogs.com
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位 置給出原文連接,否則保留追究法律責任的權利。