2012-12-17 27 views
8

Để cho phép người dùng tìm kiếm trên nhiều trường bằng Lucene 3.5, tôi hiện tạo và thêm QueryParser cho mỗi trường cần tìm kiếm DisjunctionMaxQuery. Điều này hoạt động tốt khi sử dụng HOẶC làm toán tử mặc định nhưng bây giờ tôi muốn thay đổi toán tử mặc định thành AND để nhận được kết quả chính xác hơn (và ít hơn).Lucene: Tìm kiếm nhiều trường với toán tử mặc định = AND

Sự cố là, queryParser.setDefaultOperator(QueryParser.AND_OPERATOR) bỏ lỡ nhiều tài liệu vì tất cả các cụm từ phải nằm trong trường ít nhất 1.

Ví dụ: hãy xem xét dữ liệu sau cho tài liệu: trường tiêu đề = "Ngôn ngữ lập trình", trường nội dung = "Java, C++, PHP". Nếu người dùng tìm kiếm Lập trình Java, tài liệu cụ thể này sẽ không được đưa vào kết quả do tiêu đề cũng như trường nội dung chứa tất cả các cụm từ trong truy vấn mặc dù kết hợp chúng thực hiện. Tôi muốn tài liệu này được trả về cho truy vấn trên nhưng không cho truy vấn Lập trình HTML.

Tôi đã xem xét trường bắt giữ nhưng tôi có một vài vấn đề với nó. Đầu tiên, người dùng thường xuyên bao gồm mỗi cụm từ trường trong truy vấn của họ (tác giả: bill) mà không thể thực hiện với trường catchall. Ngoài ra, tôi làm nổi bật một số lĩnh vực với FastVectorHighlighter mà đòi hỏi chúng phải được lập chỉ mục và lưu trữ. Vì vậy, bằng cách thêm một trường catchall tôi sẽ phải lập chỉ mục hầu hết cùng một dữ liệu hai lần đó là thời gian và không gian tiêu thụ.

Bất kỳ ý tưởng nào?

+0

Liên quan đến việc lập chỉ mục trường bắt giữ, bạn có quan sát thấy lần truy cập thời gian/không gian gây ra sự lo ngại không? Kinh nghiệm của tôi đã được lập chỉ mục cùng một dữ liệu trong một lĩnh vực được lưu trữ cụ thể, và sau đó thêm vào một lĩnh vực chỉ mục chỉ tổng quát có tác động khá tối thiểu về hiệu suất hoặc kích thước chỉ mục. – femtoRgon

+0

Ngoài ra, tôi tự hỏi cấu trúc của truy vấn cuối trông như thế nào. Đặc biệt, cách các truy vấn dis-max được thiết lập. Dễ dàng để giết khả năng của bạn để có được điểm số có ý nghĩa với họ. – femtoRgon

+0

@femtoRgon disjunctionMaxQuery cấu trúc là như thế này: '((tiêu đề: java title: lập trình) | (body: java body: programming)) ~ 0.2' Bạn đưa ra một điểm tốt rằng thêm một lĩnh vực catchall có thể có ít tác động như thời gian xa/không gian là có liên quan. Tôi chắc chắn đã xem xét nó nhưng quyết định chống lại nó vì tôi cũng muốn giữ khả năng tìm kiếm theo lĩnh vực, chẳng hạn như tác giả: hóa đơn. Không chỉ người dùng sử dụng tính năng này mà tôi còn sử dụng nó sau hậu trường. Cám ơn. –

Trả lời

6

Tôi nên nghiên cứu thêm một chút. Hóa ra MultiFieldQueryParser cung cấp chức năng chính xác mà tôi đang tìm kiếm. Đối với bất cứ lý do tôi đã tạo ra một QueryParser cho từng lĩnh vực tôi muốn tìm kiếm như thế này:

String[] fields = {"title", "body", "subject", "author"}; 
QueryParser[] parsers = new QueryParser[fields.length];  
for(int i = 0; i < parsers.length; i++) 
{ 
    parsers[i] = new QueryParser(Version.LUCENE_35, fields[i], analyzer); 
    parsers[i].setDefaultOperator(QueryParser.AND_OPERATOR); 
} 

này sẽ cho kết quả trong một truy vấn như thế này:

(+title:java +title:programming) | (+body:java +body:programming) 

... mà không phải là những gì tôi đã tìm kiếm. Bây giờ tôi có thể tạo một MultiFieldQueryParser đơn như thế này:

MultiFieldQueryParser parser = new MultiFieldQueryParser(Version.LUCENE_35, new String[]{"title", "body", "subject"}, analyzer); 
parser.setDefaultOperator(QueryParser.AND_OPERATOR); 

này mang lại cho tôi những câu hỏi tôi đang tìm kiếm:

+(title:java body:java) +(title:programming body:programming) 

Nhờ @seeta và @femtoRgon cho sự giúp đỡ!

2

Có lẽ những gì bạn cần là kết hợp các truy vấn Boolean nắm bắt các kết hợp khác nhau của trường và thuật ngữ. Trong ví dụ cụ thể của bạn, truy vấn có thể là -

(tiêu đề: Java AND body: programming) HOẶC (tiêu đề: lập trình AND body: Java).

Tôi không biết liệu có lớp Truy vấn hiện tại nào tạo tự động cho bạn hay không, nhưng tôi nghĩ đó là truy vấn cuối cùng chạy trên chỉ mục.

+0

Tôi nghĩ rằng bạn đang đi đúng hướng mặc dù tôi nghĩ sẽ tốt hơn khi chuyển đổi AND và OR như thế này đúng không? (tiêu đề: java HOẶC body: java HOẶC subject: java) AND (title: programming OR body: lập trình HOẶC subject: programming) ... [process additional terms] ... Tôi sẽ đăng bài thực hiện của mình khi hoàn thành cho những người khác đang tìm kiếm một giải pháp có thể. Thx cho câu trả lời. –

0

Bạn muốn để có thể tìm kiếm nhiều lĩnh vực với cùng một từ ngữ, sau đó các câu hỏi từ nhận xét của bạn:

((title:java title:programming) | (body:java body:programming))~0.2 

không thể là việc thực hiện tốt nhất.

Bạn đang nhận được điểm số từ tiêu đề hoặc điểm số từ cơ thể cho tập hợp các cụm từ kết hợp. Các trường hợp mà bạn nhấn java trong tiêu đề và lập trình trong cơ thể sẽ được đưa ra khoảng. trọng lượng bằng nhau để một cú đánh trên java trong cơ thể và không có hit trên lập trình.

Tôi nghĩ rằng một truy vấn có cấu trúc tốt hơn sẽ là:

(title:java body:java)~0.2 (title:programming body:programming)~0.2 

này có ý nghĩa hơn đối với tôi, vì bạn muốn truy vấn dismax để hạn chế điểm phát triển trên nhiều truy vấn cùng kỳ hạn (trong các lĩnh vực khác nhau), nhưng bạn muốn ghi điểm để phát triển cho các hit trên các điều kiện khác nhau, tôi tin.

Nếu cấu trúc truy vấn đó cho bạn kết quả điểm tốt hơn, giới hạn kết quả đến một điểm tối thiểu nhất định (phần trăm điểm tối đa được trả về, thay vì giá trị mã hóa đơn giản) có thể đủ để ngăn kết quả quá yếu được nhìn thấy.


tôi cũng vẫn sẽ không được tính ra lập chỉ mục một khắp mặt sân. Đó là một triển khai mà tôi đã sử dụng trước đây, trong khi lập chỉ mục BOTH trường cụ thể và trường catchall, do đó cho phép cả truy vấn chung và truy vấn một trường cụ thể. Lưu trữ chỉ mục có xu hướng khá gọn gàng với các thuật ngữ chưa được lưu trữ và thường sẽ giúp hiệu suất, nếu bạn thấy mình phải tạo các truy vấn lớn, phức tạp để bù đắp cho việc không có nó.

Nếu bạn thực sự muốn chắc chắn rằng nó cần lưu trữ tối thiểu, thậm chí bạn có thể tắt TermVectors cho lĩnh vực rằng:

new Field(name, value, Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.NO); 

Mặc dù tôi không biết bao nhiêu sự khác biệt đó thực sự sẽ làm cho.

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