Tôi đã asked a simlar question on Meta Stack Overflow, nhưng giao dịch cụ thể với việc có hay không Lucene.NET được sử dụng trên Stack Lỗi.Làm thế nào để sử dụng Lucene.NET để giúp thực hiện tìm kiếm trên một trang web như Stack Overflow?
Mục đích của câu hỏi ở đây là nhiều giả thuyết hơn, như cách tiếp cận sẽ thực hiện nếu họ sử dụng Lucene.NET làm cơ sở cho tìm kiếm tại chỗ và các yếu tố khác trong một trang web như Stack Tràn [SO].
Theo entry trên blog của tràn stack tựa đề "SQL 2008 Full-Text Search Problems" đã có một mạnh dấu hiệu cho thấy Lucene.NET đang được xem xét ở một số điểm, nhưng có vẻ như chắc chắn là không phải như vậy, theo nhận xét bởi Geoff Dalgas vào ngày 19 tháng 2 2010:
Lucene.NET không được sử dụng cho stack Overflow - chúng tôi đang sử dụng SQL server toàn văn chỉ mục. Tìm kiếm là một khu vực nơi chúng tôi tiếp tục thực hiện các thay đổi nhỏ .
Vì vậy, câu hỏi của tôi là, cách sử dụng Lucene.NET vào trang web có cùng ngữ nghĩa của Stack Tràn?
Dưới đây là một số nền tảng và những gì tôi đã thực hiện/suy nghĩ về cho đến nay (vâng, tôi đã thực hiện hầu hết những điều này và tìm kiếm là khía cạnh cuối cùng tôi phải hoàn thành):
Technologies:
Và tất nhiên, ngôi sao của chương trình, Lucene.NET.
Ý định cũng chuyển sang .NET/C# 4.0 ASAP. Mặc dù tôi không nghĩ đó là một sự thay đổi trong trò chơi, cần lưu ý.
Trước khi đi sâu vào các khía cạnh của Lucene.NET, điều quan trọng là chỉ ra các khía cạnh SQL Server 2008 của nó, cũng như các mô hình liên quan.
Models
Hệ thống này có nhiều hơn một loại mô hình chính so để Stack Overflow . Một số ví dụ về các mô hình này là:
- Câu hỏi: Đây là những câu hỏi mà mọi người có thể hỏi. Mọi người có thể trả lời các câu hỏi, giống như trên Stack Lỗi.
- Lưu ý: Đây là những dự đoán một chiều, do đó trái ngược với câu hỏi, bạn đang đưa ra tuyên bố về nội dung. Mọi người không thể đăng trả lời cho bài đăng này.
- Sự kiện: Đây là dữ liệu về sự kiện thời gian thực. Nó có thông tin vị trí, thông tin ngày/giờ.
Điều quan trọng cần lưu ý về các mô hình:
- Tất cả đều có một tên/Tiêu đề (văn bản) bất động sản và một cơ thể (HTML) tài sản (các định dạng không liên quan, như nội dung sẽ phân tích cú pháp một cách thích hợp để phân tích).
- Mỗi thể hiện của một mô hình có một URL duy nhất trên trang web
Sau đó, có những điều mà ngăn xếp Overflow cung cấp mà IMO, được trang trí với các mô hình. Những trang trí có thể có cardinalities khác nhau, hoặc là một-một hoặc một-nhiều:
- Votes: keyed trên người dùng
- Trả lời: Không bắt buộc, là một ví dụ, xem trường hợp ghi chú trên
- Được yêu thích: Mô hình có được liệt kê là yêu thích của người dùng không?
- Nhận xét: (tùy chọn)
- Hiệp hội thẻ: Thẻ nằm trong một bảng riêng biệt, để không sao chép thẻ cho từng mô hình. Có một liên kết giữa mô hình và bảng liên kết thẻ, sau đó từ bảng liên kết thẻ đến bảng thẻ.
Và có đếm sẽ tính toán hỗ trợ mà chính họ là one-to-one trang trí với các mô hình được vừa khít với họ theo cách tương tự (thường là bằng một loại mô hình id và mô hình id):
- Số phiếu bầu: Tổng số phiếu bầu, số phiếu tiêu cực, Wilson Score interval (điều này rất quan trọng, nó sẽ xác định mức độ tin cậy dựa trên phiếu bầu cho mục nhập, phần lớn, giả sử giới hạn dưới của khoảng thời gian Wilson).
Trả lời (câu trả lời) là các mô hình có hầu hết các trang trí mà hầu hết các mẫu đều có, không có tiêu đề hoặc url và mô hình có trả lời là tùy chọn hay không. Nếu trả lời được cho phép, đó là tất nhiên một mối quan hệ một-nhiều.
SQL Server 2008
Các bảng khá nhiều theo cách bố trí của các mô hình trên, với các bảng riêng biệt cho trang trí, cũng như một số bảng hỗ trợ và quan điểm, thủ tục lưu trữ, vv
Cần lưu ý rằng quyết định không sử dụng tìm kiếm toàn văn bản chủ yếu dựa trên thực tế là nó không chuẩn hóa điểm số như Lucene.NET. Tôi mở để gợi ý về cách sử dụng tìm kiếm dựa trên văn bản, nhưng tôi sẽ phải thực hiện tìm kiếm trên nhiều loại mô hình, vì vậy hãy nhớ rằng tôi sẽ cần phải chuẩn hóa số điểm bằng cách nào đó.
Lucene.NET
Đây là nơi các dấu hỏi lớn đặt ra là. Dưới đây là những suy nghĩ của tôi cho đến nay trên Stack Chức năng tràn cũng như cách thức và những gì tôi đã thực hiện.
Indexing
Câu hỏi/Models
Tôi tin rằng mỗi mô hình cần phải có một chỉ số của riêng nó chứa một id duy nhất để nhanh chóng tìm nó lên dựa trên một trường hợp hạn của id đó (lập chỉ mục , không được phân tích).
Trong lĩnh vực này, tôi đã xem xét việc Lucene.NET phân tích từng câu hỏi/mô hình và từng câu trả lời riêng lẻ. Vì vậy, nếu có một câu hỏi và năm câu trả lời, câu hỏi và mỗi câu trả lời sẽ được lập chỉ mục dưới dạng một đơn vị riêng biệt.
Ý tưởng ở đây là điểm liên quan mà Lucene.NET trả về sẽ dễ dàng so sánh giữa các mô hình dự án theo những cách khác nhau (ví dụ, không có câu trả lời).
Ví dụ: câu hỏi đặt chủ đề và sau đó câu trả lời sẽ giải thích rõ hơn về chủ đề.
Đối với một ghi chú không có câu trả lời, nó sẽ xử lý vấn đề trình bày chủ đề và sau đó xây dựng trên đó.
Tôi tin rằng điều này sẽ giúp làm cho điểm số liên quan phù hợp hơn với nhau.
Thẻ
Ban đầu, tôi nghĩ rằng những nên được giữ trong một chỉ số riêng biệt với nhiều lĩnh vực trong đó có id để các tài liệu trong chỉ số mô hình thích hợp. Hoặc, nếu quá lớn, có một chỉ mục chỉ với các thẻ và một chỉ mục khác duy trì mối quan hệ giữa chỉ mục thẻ và các câu hỏi mà chúng được áp dụng. Bằng cách này, khi bạn click vào một từ khóa (hoặc sử dụng các cấu trúc URL), thật dễ dàng để xem một cách liên tục mà bạn chỉ cần "mua vào" nếu bạn thành công:
- Nếu thẻ tồn tại
- những câu hỏi các thẻ được gắn liền với
- các câu hỏi tự
Tuy nhiên, trong thực tế, thực hiện một truy vấn của tất cả các mục dựa trên các thẻ (như cách nhấp vào một thẻ trong stack Overflow) là cực kỳ dễ với SQL Server 2008. Dựa trên mô hình trên, nó chỉ đơn giản đòi hỏi một truy vấn như:
select
m.Name, m.Body
from
Models as m
left outer join TagAssociations as ta on
ta.ModelTypeId = <fixed model type id> and
ta.ModelId = m.Id
left outer join Tags as t on t.Id = ta.TagId
where
t.Name = <tag>
Và kể từ khi sản phẩm nhất định được chia sẻ trên tất cả các mô hình, nó dễ dàng, đủ để làm một UNION
giữa mô hình các loại/bảng khác nhau và tạo ra một tập hợp các các kết quả.
Điều này sẽ mang tính hậu môn đến TermQuery
trong Lucene.NET (Tôi tham khảo Java documentation vì nó toàn diện, và Lucene.NET được hiểu là bản dịch từng dòng Lucene, vì vậy tất cả tài liệu là tương tự).
Vấn đề đi kèm với việc sử dụng Lucene.NET ở đây là thứ tự sắp xếp. Điểm liên quan cho một TermQuery khi nói đến thẻ không liên quan. Đó là 1 hoặc 0 (hoặc là có hoặc không).
Tại thời điểm này, điểm số tin cậy (khoảng thời gian Wilson) đi vào hoạt động để đặt hàng kết quả.
Điểm này có thể được lưu trữ trong Lucene.NET, nhưng để sắp xếp kết quả trên trường này, nó sẽ dựa vào các giá trị được lưu trữ trong bộ nhớ cache trường, đó là điều tôi thực sự muốn tránh. Đối với một số lượng lớn tài liệu, bộ nhớ cache trường có thể phát triển rất lớn (điểm Wilson là gấp đôi, và bạn sẽ cần một gấp đôi cho mỗi tài liệu, có thể là một mảng lớn).
Cho rằng tôi có thể thay đổi câu lệnh SQL để thứ tự dựa trên các Wilson điểm khoảng như thế này:
select
m.Name, m.Body
from
Models as m
left outer join TagAssociations as ta on
ta.ModelTypeId = <fixed model type id> and
ta.ModelId = m.Id
left outer join Tags as t on t.Id = ta.TagId
left outer join VoteTallyStatistics as s on
s.ModelTypeId = ta.ModelTypeId and
s.ModelId = ta.ModelId
where
t.Name = <tag>
order by
--- Use Id to break ties.
s.WilsonIntervalLowerBound desc, m.Id
Nó có vẻ như một sự lựa chọn dễ dàng để sử dụng để xử lý các mảnh stack chức năng Overflow "nhận tất cả các mục được gắn thẻ với < thẻ > ".
Trả lời
Ban đầu, tôi nghĩ đây là một chỉ số riêng biệt của riêng nó, với một chìa khóa trở lại vào chỉ số câu hỏi.
Tôi nghĩ rằng phải có sự kết hợp của mỗi mô hình và mỗi câu trả lời (nếu có) và điểm số liên quan trên các mô hình khác nhau sẽ "cân bằng" hơn khi so sánh với nhau.
Điều này tất nhiên sẽ làm nổi bật chỉ mục. Tôi hơi thoải mái với điều đó ngay bây giờ.
Hoặc, có cách nào để lưu trữ, mô hình và trả lời dưới dạng tài liệu riêng lẻ trong Lucene.NET và sau đó lấy cả điểm và mức độ phù hợp cho truy vấn xử lý cả hai tài liệu dưới dạng? Nếu vậy, thì đây sẽ là lý tưởng.
Tất nhiên, câu hỏi về trường nào sẽ được lưu trữ, lập chỉ mục, phân tích (tất cả các hoạt động có thể là các hoạt động riêng biệt hoặc kết hợp và kết hợp)? Chỉ bao nhiêu một chỉ mục?
Điều gì về việc sử dụng các trình chặn/đánh số đặc biệt cho các lỗi chính tả (sử dụng Metaphone) cũng như các từ đồng nghĩa (có thuật ngữ trong cộng đồng tôi sẽ dịch vụ có thuật ngữ/thuật ngữ riêng cho một số thứ nhất định)?
Boost
này liên quan đến lập chỉ mục tất nhiên, nhưng tôi nghĩ rằng nó xứng đáng đó là phần riêng.
Bạn có đang thúc đẩy trường và/hoặc tài liệu không? Nếu vậy, làm thế nào để bạn tăng cường chúng? Là hằng số tăng cường cho các trường nhất định? Hoặc nó được tính toán lại cho các trường có dữ liệu bỏ phiếu/xem/yêu thích/bên ngoài.
Ví dụ: trong tài liệu, tiêu đề có tăng cường trên cơ thể không? Nếu có, bạn nghĩ hoạt động nào tốt? Điều gì về thẻ?
Suy nghĩ ở đây giống như ở dọc theo các dòng Stack Tràn. Các điều khoản trong tài liệu có liên quan, nhưng nếu một tài liệu được gắn thẻ với thuật ngữ, hoặc nó nằm trong tiêu đề, thì nó sẽ được tăng cường.
Shashikant Kore cho thấy một cấu trúc tài liệu như thế này:
- Tiêu đề
- Câu hỏi
- Được chấp nhận trả lời (Hoặc câu trả lời đã bỏ phiếu đánh giá cao nếu không có câu trả lời được chấp nhận)
- Tất cả các câu trả lời kết hợp
Và sau đó sử dụng tăng nhưng không dựa trên giá trị bỏ phiếu thô. Tôi tin rằng tôi có được bao phủ với khoảng thời gian Wilson Điểm.
Câu hỏi đặt ra là liệu tăng cường có được áp dụng cho toàn bộ tài liệu không? Tôi đang nghiêng về phía không có trên này, bởi vì nó sẽ có nghĩa là tôi phải reindex tài liệu mỗi khi người dùng bình chọn trên mô hình.
Tìm kiếm Items Tagged
Tôi ban đầu nghĩ rằng khi truy vấn cho một từ khóa (do đặc biệt nhấp vào một hoặc sử dụng cấu trúc URL cho nhìn lên nội dung đánh dấu), đó là một TermQuery đơn giản so với chỉ số thẻ cho thẻ, sau đó trong chỉ mục liên kết (nếu cần), sau đó quay lại các câu hỏi, Lucene.NET xử lý điều này một cách nhanh chóng.
Tuy nhiên, với các lưu ý ở trên về việc dễ dàng thực hiện điều này trong SQL Server, tôi đã chọn tuyến đường đó khi tìm kiếm các mục được gắn thẻ.
chung Tìm
Bây giờ, câu hỏi xuất sắc nhất là khi thực hiện một cụm từ chung chung hoặc cụm từ tìm kiếm đối với nội dung, những gì và làm thế nào để bạn tích hợp các thông tin khác (ví dụ như phiếu) để xác định kết quả theo đúng thứ tự? Ví dụ, khi thực hiện tìm kiếm này trên ASP.NET MVC on Stack Overflow, đây là những tallies cho năm kết quả đầu (khi sử dụng các tab liên quan):
q votes answers accepted answer votes asp.net highlights mvc highlights
------- ------- --------------------- ------------------ --------------
21 26 51 2 2
58 23 70 2 5
29 24 40 3 4
37 15 25 1 2
59 23 47 2 2
Lưu ý rằng những điểm nổi bật chỉ trong tiêu đề và tóm tắt trên trang kết quả và chỉ là các chỉ số nhỏ về tần suất của cụm từ đúng trong tài liệu, tiêu đề, thẻ, trả lời (tuy nhiên chúng được áp dụng, đó là một câu hỏi hay).
Tất cả điều này được tập hợp lại như thế nào? Tại thời điểm này, tôi biết rằng Lucene.NET sẽ trả lại một điểm liên quan chuẩn hóa, và dữ liệu bỏ phiếu sẽ cho tôi một khoảng thời gian Wilson mà tôi có thể sử dụng để xác định điểm số tin cậy.
Tôi nên xem xét kết hợp hai điểm số để chỉ ra thứ tự sắp xếp của tập hợp kết quả dựa trên mức độ liên quan và sự tự tin như thế nào?
Rõ ràng với tôi rằng cần có một số mối quan hệ giữa hai mối quan hệ đó, nhưng mối quan hệ đó sẽ tránh né tôi vào thời điểm này. Tôi biết tôi phải tinh chỉnh nó như thời gian trôi qua, nhưng tôi thực sự bị mất phần này.
những suy nghĩ ban đầu của tôi là nếu số điểm liên quan là beween 0 và 1 và điểm số tín nhiệm là giữa 0 và 1, sau đó tôi có thể làm một cái gì đó như thế này:
1/((e^cs) * (e^rs))
Bằng cách này, ta có một giá trị được chuẩn tiếp cận 0 kết quả có liên quan hơn và tự tin hơn, và nó có thể được sắp xếp trên đó.
Vấn đề chính với điều đó là nếu việc tăng cường được thực hiện trên thẻ và trường tiêu đề, thì điểm liên quan nằm ngoài giới hạn từ 0 đến 1 (phần trên sẽ bị vô hiệu hóa, và tôi không biết cách để đối phó với điều đó).
Ngoài ra, tôi tin rằng tôi sẽ phải điều chỉnh điểm số tin cậy để tính toán số phiếu bầu bị âm hoàn toàn. Vì số phiếu bầu là kết quả âm hoàn toàn trong khoảng thời gian Wilson với điểm thấp hơn là 0, thứ gì đó có -500 phiếu có cùng điểm số tin cậy với -1 phiếu, hoặc 0 phiếu.
May thay, giới hạn trên giảm từ 1 xuống 0 khi số lượt bỏ phiếu phủ định tăng lên. Tôi có thể thay đổi số điểm tự tin để trở thành một dao động từ -1 đến 1, như vậy:
confidence score = votetally < 0 ?
-(1 - wilson score interval upper bound) :
wilson score interval lower bound
Vấn đề với điều này là cắm vào 0 vào phương trình sẽ xếp hạng tất cả các mục có zero phiếu thấp hơn so với số lần bỏ phiếu phủ định.
Để kết thúc, tôi nghĩ nếu điểm số tin cậy sẽ được sử dụng trong một phương trình đối ứng như trên (tôi lo ngại về tràn rõ ràng), thì nó cần phải được làm lại để luôn dương. Một cách để đạt được điều này là:
confidence score = 0.5 +
(votetally < 0 ?
-(1 - wilson score interval upper bound) :
wilson score interval lower bound)/2
Các mối quan tâm khác của tôi là cách thực sự thực hiện tính toán cho Lucene.NET và SQL Server. Tôi do dự để đặt điểm số niềm tin vào chỉ số Lucene vì nó đòi hỏi phải sử dụng bộ nhớ cache trường, có thể có một tác động rất lớn đến mức tiêu thụ bộ nhớ (như đã đề cập trước đó).
Ý tưởng tôi có là lấy điểm liên quan từ Lucene.NET và sau đó sử dụng table-valued parameter để truyền số điểm đến SQL Server (cùng với id của các mục cần chọn), tại thời điểm này tôi sẽ thực hiện tính toán với điểm số tin cậy và sau đó trả lại dữ liệu đúng thứ tự.
Như đã nêu trước đây, có rất nhiều câu hỏi khác mà tôi có về vấn đề này và câu trả lời đã bắt đầu đóng khung mọi thứ và sẽ tiếp tục mở rộng khi mọi thứ như câu hỏi và câu trả lời được giải thích.
@Paul: Tôi đã cập nhật câu hỏi để phản ánh cách dữ liệu bầu chọn (điểm tin cậy) liên quan đến điểm liên quan cũng như suy nghĩ về trả lời. Tôi không nghĩ rằng tôi sẽ sử dụng danh tiếng của người dùng để cân nhắc kết quả sắp xếp tìm kiếm, nhưng xét về các câu trả lời liên tiếp về mặt phiếu bầu thì thật dễ dàng để thực hiện trong SQL Server. – casperOne