2011-11-10 42 views
5

tôi phải làm tìm kiếm văn bản đầy đủ trong NHibernateNHibernate + SQLServer toàn văn tìm kiếm

Đối với sau hoạt động trước đây tôi đang sử dụng Lucene.Net

Tôi có một bảng gọi là ứng cử viên

Đối với truy vấn văn bản đầy đủ Lucene sẽ trả về tất cả Id ứng cử viên từ chỉ mục lucene và dạng id mà tôi đưa vào truy vấn trong ứng cử viên và trả lại kết quả

Nhưng vấn đề là có hơn 10 Thiếu lý lịch ứng viên có sẵn để Lucene rất chậm vì giá trị bộ lọc từ 10 hàng Lc và đặt giá trị trả về cho trong truy vấn đối với ứng cử viên và một lần nữa lọc ứng cử viên đang tiến hành quá nhiều thời gian

Ngoài ra tôi có một tiêu chí phân trang và cho mỗi trang tôi trở 100 ứng cử viên

bây giờ tôi thêm mới bảng candidate_full_text trong bảng mà tôi cấu hình chỉ mục văn bản đầy đủ trong SQLServer 2000 bây giờ tôi muốn truy vấn sử dụng NHibernate DetachedCriteria như sau

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) 

điều sau tôi phải làm trong truy vấn duy nhất với DetachedCriteria Và cột quan trọng đối với chỉ số candidate_full_text là ứng cử viên bảng id .. Ở đây tôi đưa ra mô hình bảng 1) ứng cử viên (trường Min)

Id - int,

Tên - varchar,

Dob - datetime,

2) candidate_full_text

id - int,

candidate_resume_full_text -ntext, (cấu hình chỉ số toàn văn)

candidate_id - int

+2

Tôi sẽ không tính vào tìm kiếm toàn văn bản, đặc biệt là trên Sql Server 2000, nhanh hơn lucene. Lucene nói chung là rất nhanh, ngay cả đối với số lượng dữ liệu khổng lồ. Bạn đã xem xét loại bỏ truy vấn IN bằng cách đặt tất cả các dữ liệu cần thiết trong lucene, để bạn tránh đánh máy chủ Sql hoàn toàn? –

+0

Tôi sẽ tìm kiếm sqlserver fulltext từ lucene để hợp lý hơn là lý do kỹ thuật .. tôi không thể đặt tất cả dữ liệu trong lucene vì orm im sử dụng nhibernate..im sử dụng lucene cho chỉ một mục đích tức là tìm kiếm toàn văn – Anand

+0

Tôi đồng ý với Jonas H. rằng Lucene nói chung là một giải pháp thực hiện nhiều hơn SQL FTS. Tuy nhiên, nếu hiệu suất của SQL FTS là đầy đủ, sử dụng nó mang lại cho bạn lợi ích của việc có thể liên kết kết nối FTS (thông qua hàm CONTAINSTABLE hoặc FREETEXTTABLE) với dữ liệu quan hệ khác, làm cho việc lọc và nhóm phức tạp hơn . –

Trả lời

2

Nếu bạn có thể sử dụng SQL Server FTS thay vì Lucene và hiệu suất chấp nhận được, bạn có thể tận dụng khả năng tham gia quan hệ giữa kết quả SQL Server FTS và dữ liệu quan hệ khác trong cơ sở dữ liệu của bạn. Để thực hiện các phép nối này, bạn nên sử dụng hàm CONTAINSTABLE, thay vì vị từ CONTAINS.

Sử dụng ví dụ của bạn, hãy thiết lập các bảng sau trong 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) 
) 

Sau đó bạn có thể tạo một tên truy vấn tham số trong nHibernate một cái gì đó dọc theo những dòng:

<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> 

Lưu ý cách này truy vấn liên quan đến kết quả của hàm CONTAINSTABLE đến bảng khác trong cơ sở dữ liệu của bạn. Bằng cách sử dụng SQL FTS, thật dễ dàng để tham gia các kết quả FTS với các truy vấn quan hệ phức tạp trên các dữ liệu khác trong DB của bạn. Khả năng này là một trong những lợi ích chính của việc sử dụng SQL Server FTS trên Lucene và có thể là một lý do để chọn nó trên Lucene mặc dù hiệu năng tổng thể của nó kém hơn.

Cuối cùng, bạn có thể điền vào các thông số của bạn trong ứng dụng C# của bạn và thực hiện truy vấn bằng cách sử dụng đối tượng 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(); 

Các ROWNUMBER() chức năng không có sẵn trong SQL Server 2000, mà bạn đang sử dụng nhưng tôi nghĩ có nhiều công việc khác để thực hiện phân trang (xem ví dụ this article). (Hoặc bạn có thể muốn nâng cấp SQL Server của bạn lên năm 2008, chạy FTS trong quá trình và có hiệu suất tốt hơn nhiều!)

Tôi nghĩ một giải pháp dọc theo những dòng này sẽ đáp ứng nhu cầu của bạn.

Các vấn đề liên quan