2011-11-10 38 views
5

我必須做全文搜索NHibernate的的NHibernate + SqlServer的全文搜索

對於下列以前我使用Lucene.Net

我有一個名爲候選

對於全文查詢表操作Lucene的將Lucene索引返回所有候選編號,並形成ID我把查詢候選並返回結果

但問題是,有超過10個候選人缺乏的簡歷可以使Lucene是因爲很慢從10路行篩選值,並把返回值查詢針對候選人,再次篩選候選人花費過多時間

還我一個傳呼標準,併爲每個頁面我回100名候選人

現在我增添了新的表在表candidate_full_text 我在SQLSERVER配置全文索引2000 現在我想使用NHibernate的DetachedCriteria如下

1) Select candidate with some filters 

2) Execute the function ContainsTable for candidate_full_text table 
(which returns candidate tables id as key and rank of occurrence of the search string) 

3) join the result from 1 & 2 

4) Apply paging criteria (ie return 1st 100,2nd 100,3rd 100.. etc) according to page no 

5) return the result by order of rank column (which is return by ContainsTable) 

下面的事情我有一個查詢做的DetachedCriteria 和查詢對於candidate_full_text索引鍵列候選表ID .. 1)候選人在這裏,我給出的錶款(最小領域)

標識 - INT,

名稱 - VARCHAR,

杜伯 - 日期時間,

2)candidate_full_text

ID - INT,

candidate_resume_full_text -ntext,(配置全文索引)

candidate_id - 詮釋

+2

我不會指望全文搜索,特別是在Sql Server 2000上,要比lucene更快。即使對於大數據量,Lucene通常也是非常快的。您是否考慮通過將所有需要的數據放在lucene中來消除IN查詢,以避免完全打到Sql服務器? –

+0

我要從lucene的sqlserver全文搜索更多的邏輯,而不是技術上的原因..我不能把所有的數據在lucene中,因爲對於orm im使用nhibernate ..im使用lucene只有一個目的,即全文搜索 – Anand

+0

我同意Jonas H. Lucene通常比SQL FTS更具性能的解決方案。但是,如果SQL FTS的性能足夠好,那麼使用它可以讓您將FTS結果(通過CONTAINSTABLE或FREETEXTTABLE函數)與其他關係數據進行關聯連接,從而使得執行真正複雜的過濾和分組變得容易。 –

回答

2

如果你能夠使用的,而不是Lucene的SQL服務器FTS和性能是可以接受的,你可以採取的能力優勢在SQL Server FTS結果和數據庫中的其他關係數據之間進行關係連接。要做這些連接,你應該使用CONTAINSTABLE函數,而不是CONTAINS謂詞。

使用您的例子,讓我們建立在SQL Server下表:

create table Candidate 
( 
Id int primary key, 
Name varchar(50), 
Dob datetime 
) 

create table Candidate_Full_Text 
(
id int primary key, 
candidate_resume_full_text ntext, -- FTS column 
candidate_id int foreign key references Candidate(Id) 
) 

然後,您可以創建NHibernate的東西沿着這些線路參數化的命名查詢:

<sql-query name="CandidateSearch"> 
    <![CDATA[ 
    SELECT TOP (:take) * 
     FROM 
      (SELECT c.Id, c.Name, ft.[RANK], ROW_NUMBER() OVER(ORDER BY ft.[RANK] desc) as rownum   
      FROM ContainsTable(Candidate_full_text, candidate_resume_full_text , :phrase, LANGUAGE 1033) ft 
         INNER JOIN Candidate c on ft.[KEY] = c.Id 
      WHERE c.Name = :name and c.Dob > :dob 
      ) a 
     WHERE a.rownum > :skip ORDER BY a.rownum 
    ]]> 
</sql-query> 

注意如何查詢將CONTAINSTABLE函數的結果關聯地連接到數據庫中的其他表。通過使用SQL FTS,可以輕鬆地將FTS結果與複雜的關係查詢結合在數據庫中的其他數據上。此功能是使用SQL Server FTS而不是Lucene的主要優勢之一,並且可以通過Lucene選擇它,儘管它的整體性能較差。

最後,你可以在你的參數填寫你的C#應用​​程序,並使用NHibernate的ISession的對象執行查詢:

 int take = 5; 
     int skip = 10; 
     string phrase = "(team NEAR player) OR (teamwork NEAR coopertive)"; 
     string name = "John Doe"; 
     DateTime dob = new DateTime(1963, 7, 1); 

     var results = _session.GetNamedQuery("ExpandedSearchTerm") 
           .SetString("phrase", phrase) 
           .SetDateTime("dob", dob) 
           .SetString("phrase", phrase) 
           .SetInt32("take", take) 
           .SetInt32("skip", skip) 
           .List(); 

的ROWNUMBER()函數是不是在SQL Server 2000中,您使用的是可,但我認爲還有其他解決辦法可以用於分頁(例如,請參閱this article)。 (或者你可能想升級你的SQL Server到2008,它運行FTS並具有更好的性能!)

我認爲沿這些方向的解決方案將滿足您的需求。