2011-11-23 21 views
5

Tôi muốn tìm kiếm chỉ mục của mình trên hai trường có tên là "a" và "b". Tôi được cung cấp các tìm kiếm như Freud -- theories of psychology và tôi muốn thực hiện truy vấn sau:Làm cách nào để kết hợp hai truy vấn Lucene bằng OR?

(a="Freud" AND b="theories of psychology") OR (b="Freud" AND a="theories of psychology") 

Làm cách nào để thực hiện việc này? Cho đến nay tôi có Lucene xây dựng hai nửa (firstHalfsecondHalf) sử dụng MultiFieldQueryParser, sau đó tôi đã kết hợp chúng với

BooleanQuery combined = new BooleanQuery(); 
combined.add(firstHalf, BooleanClause.Occur.SHOULD); 
combined.add(secondHalf, BooleanClause.Occur.SHOULD); 

Nhưng combined cho phép kết quả được trả về nơi chỉ có "lý thuyết" được tìm thấy và không "tâm lý" , nơi tôi chắc chắn muốn cả hai điều khoản. Có vẻ như Lucene đang tách "lý thuyết tâm lý học" thành ba từ và kết hợp chúng với OR. Làm thế nào để ngăn chặn điều này?

firstHalf trông giống như:

Query firstHalf = MultiFieldQueryParser.parse(Version.LUCENE_33, 
     new String[]{"Freud", "theories of psychology"}, 
     new String[]{"a", "b"}, 
     new BooleanClause.Occur[]{BooleanClause.Occur.MUST, BooleanClause.Occur.MUST}, 
     analyzer); 

nơi analyzer chỉ là một đối tượng StandardAnalyzer.

+0

Được chỉ nói rằng Lucene không hỗ trợ chuỗi Boolean như thế này, và rằng NÊN = HOẶC!. Trong trường hợp đó, _Lucene trong Action_ 2nd Edition là sai trên trang 95. :) Vì vậy, bây giờ tôi biết _why_ truy vấn của tôi bị hỏng, chỉ không biết làm thế nào để sửa chữa nó vẫn còn. – dmn

+0

Bạn có chắc chắn truy vấn là chính xác không? Truy vấn 'lý thuyết của tâm lý học 'có nghĩa là ít nhất một trong ba từ phải xảy ra ở đâu đó, nhưng không có từ nào trong số đó là từ bắt buộc. –

+0

@KaiChan Nope, tôi đã phải sửa đổi điều này để đặt hạn chế đó. Tôi nghĩ rằng tôi đã nhận nó mặc dù. :) – dmn

Trả lời

2

Máy phân tích chuẩn sẽ mã hóa. Vì vậy, truy vấn theories of psychology tương đương với theories OR of OR psychology.

Nếu bạn muốn tìm cụm từ "lý thuyết tâm lý", hãy sử dụng PhraseQuery, hoặc chú ý rằng QueryParser mặc định sẽ dịch các trích dẫn có nghĩa là cụm từ (tức là thay đổi mã thành "\"theories of psychology\"").

Và có, có một ý nghĩa trong đó Lucene không sử dụng logic Boolean, nhưng nó là kỹ thuật và không thực sự có liên quan ở đây.

3

Tự tìm hiểu, nhưng bây giờ mã này dài hơn đáng kể; nếu bất cứ ai biết một giải pháp thanh lịch hơn, xin vui lòng gửi và tôi sẽ sẵn sàng khen thưởng. :) (Mặc dù tôi sẽ làm điều này vào một phương pháp trong thời gian ngắn ... nhưng đây là phiên bản đầy đủ về những gì đang xảy ra ...)

QueryParser parser = new QueryParser(Version.LUCENE_33, "a", analyzer); 
parser.setDefaultOperator(QueryParser.AND_OPERATOR); 
Query a_0 = parser.parse("Freud"); 
parser = new QueryParser(Version.LUCENE_33, "b", analyzer); 
parser.setDefaultOperator(QueryParser.AND_OPERATOR); 
Query b_1 = parser.parse("theories of psychology"); 

BooleanQuery firstHalf = new BooleanQuery(); 
firstHalf.add(a_0, BooleanClause.Occur.MUST); 
firstHalf.add(b_1, BooleanClause.Occur.MUST); 

parser = new QueryParser(Version.LUCENE_33, "b", analyzer); 
parser.setDefaultOperator(QueryParser.AND_OPERATOR); 
Query b_0 = parser.parse("Freud"); 
parser = new QueryParser(Version.LUCENE_33, "a", analyzer); 
parser.setDefaultOperator(QueryParser.AND_OPERATOR); 
Query a_1 = parser.parse("theories of psychology"); 

BooleanQuery secondHalf = new BooleanQuery(); 
secondHalf.add(b_0, BooleanClause.Occur.MUST); 
secondHalf.add(a_1, BooleanClause.Occur.MUST); 

BooleanQuery combined = new BooleanQuery(); 
combined.add(firstHalf, BooleanClause.Occur.SHOULD); 
combined.add(secondHalf, BooleanClause.Occur.SHOULD); 

Hóa ra SHOULD không làm việc theo cách tôi cần nó tới đây. Hy vọng rằng một người nào đó thấy điều này hữu ích và tôi không chỉ nói chuyện với tôi ở nơi công cộng;)

+1

Đó là kinh nghiệm gần đây của tôi rằng trong việc học Lucene, bạn nên tránh QueryParser và cố gắng để mảnh tất cả mọi thứ với nhau từ các loại truy vấn trực tiếp cơ bản. Bạn sẽ hiểu rõ hơn về Lucene và sẽ không bị phân tâm bởi cú pháp truy vấn. Như Xodarap đề cập, những gì bạn thực sự muốn ở đây là PhraseQuery.Những gì bạn có bây giờ sẽ phù hợp với các tài liệu với "lý thuyết" "của" "tâm lý học" trong bất kỳ thứ tự hoặc vị trí, không phải là cụm từ chính xác. (Trên thực tế, StandardAnalyzer sẽ lọc ra "của", vì vậy ngay cả PhraseQuery sẽ không khớp với cụm từ chính xác của bạn ... nhưng đó là giới hạn tìm kiếm mà chúng tôi thường chỉ chấp nhận.) – Jegschemesch

2

Tôi đã viết lớp dưới đây để tạo ra các truy vấn mờ bị xâu chuỗi, trong đó thuật ngữ phải được tìm kiếm trên nhiều trường. Truy vấn kết hợp có thể được truy xuất bằng cách gọi phương thức GetQuery().

public class QueryParam 
{ 
    public string[] Fields { get; set; } 
    public string Term { get; set; } 

    private QueryParam _andOperandSuffix; 
    private QueryParam _orOperandSuffix; 

    private readonly BooleanQuery _indexerQuery = new BooleanQuery();   

    public QueryParam(string term, params string[] fields) 
    { 
     Term = term; 
     Fields = fields; 
    } 

    public QueryParam And(QueryParam queryParam) 
    { 
     _andOperandSuffix = queryParam; 
     return this; 
    } 

    public QueryParam Or(QueryParam queryParam) 
    { 
     _orOperandSuffix = queryParam; 
     return this; 
    } 

    public BooleanQuery GetQuery() 
    {    
     foreach (var field in Fields) 
      _indexerQuery.Add(new FuzzyQuery(new Term(field, Term)), Occur.SHOULD); 

     if (_andOperandSuffix != null) 
      _indexerQuery.Add(_andOperandSuffix.GetQuery(),Occur.MUST); 

     if (_orOperandSuffix != null) 
      _indexerQuery.Add(_orOperandSuffix.GetQuery(), Occur.SHOULD); 

     return _indexerQuery; 
    } 

} 

Ví dụ:

var leftquery = new QueryParam("Freud", "a").And(new QueryParam("theories of psychology", "b")); 
var rightquery = new QueryParam("Freud", "b").And(new QueryParam("theories of psychology", "a")); 
var query = leftquery.Or(rightquery);    
Các vấn đề liên quan