Если вы можете использовать SQL Server FTS вместо Lucene и производительность является приемлемой, вы можете воспользоваться возможностью выполнять реляционные объединения между результатами 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, который вы используете, но я думаю, что существуют другие способы обхода страниц (см., Например, эту статью ). (Или, возможно, вы захотите обновить SQL Server до 2008 года, который работает в процессе FTS и имеет гораздо лучшую производительность!)
Я думаю, что решение в этом направлении удовлетворит ваши потребности.