2012-05-15 24 views
6

Có thể sử dụng Lucene SpanQuery để tìm tất cả các lần xuất hiện mà các thuật ngữ "đỏ" "xanh lục" và "xanh" tất cả xuất hiện trong một câu không?Tìm kiếm nhận biết câu với Lucene SpanQueries

Cách tiếp cận đầu tiên (không đầy đủ/không chính xác) của tôi là viết một trình phân tích đặt một dấu hiệu dấu câu đặc biệt và bắt đầu câu ở cùng vị trí với từ đầu tiên của câu và sau đó truy vấn tương tự sau:

SpanQuery termsInSentence = new SpanNearQuery(
    SpanQuery[] { 
    new SpanTermQuery(new Term (MY_SPECIAL_SENTENCE_TOKEN)), 
    new SpanTermQuery(new Term ("red")), 
    new SpanTermQuery(new Term ("green")), 
    new SpanTermQuery(new Term ("blue")), 
    }, 
    999999999999, 
    false 
); 

SpanQuery nextSentence = new SpanTermQuery(new Term (MY_SPECIAL_SENTENCE_TOKEN)); 

SpanNotQuery notInNextSentence = new SpanNotQuery(termsInSentence,nextSentence); 

vấn đề, tất nhiên, là nextSentence là không thực sự tiếp theo câu, đó là bất kỳ câu đánh dấu, trong đó có một trong những câu nói đó termsInSentence trận đấu. Do đó điều này sẽ không hoạt động.

Cách tiếp cận tiếp theo của tôi là tạo trình phân tích đặt mã thông báo trước câu (nghĩa là trước từ từ đầu tiên thay vì ở cùng vị trí với từ đầu tiên). Vấn đề với điều này là sau đó tôi phải tính đến khoản bù trừ thêm gây ra bởi MY_SPECIAL_SENTENCE_TOKEN. Hơn nữa, điều này đặc biệt xấu khi tôi sử dụng một mẫu ngây thơ để chia nhỏ các câu (ví dụ: tách trên /\.\s+[A-Z0-9]/) vì tôi sẽ phải tính tất cả các dấu câu (sai) khi tìm kiếm USS Enterprise.

Vậy ... tôi nên tiếp cận điều này như thế nào?

Trả lời

1

Tôi sẽ lập chỉ mục mỗi câu dưới dạng tài liệu Lucene, bao gồm trường đánh dấu nguồn tài liệu mà câu đến từ đó. Tùy thuộc vào tài liệu nguồn của bạn, chi phí của câu/LuceneDoc có thể chấp nhận được.

0

Thực ra, có vẻ như bạn khá gần với giải pháp. Tôi nghĩ rằng việc lập chỉ mục một lá cờ kết thúc là một cách tiếp cận tốt. Vấn đề là cờ kết thúc của bạn nằm trong số SpanNearQuery của bạn, đó là điều bạn đang vứt bỏ. Bạn đang yêu cầu nó tìm một khoảng thời gian chứa cả và không chứa MY_SPECIAL_SENTENCE_TOKEN. Truy vấn mâu thuẫn với chính nó, vì vậy, tất nhiên, nó sẽ không tìm thấy bất kỳ trận đấu nào. Những gì bạn thực sự cần biết, là ba thuật ngữ ("đỏ", "xanh" và "xanh dương") xuất hiện trong một khoảng không trùng với MY_SPECIAL_SENTENCE_TOKEN (nghĩa là, mã thông báo câu không xuất hiện ở giữa các cụm từ đó điều kiện).

Ngoài ra, việc thiếu tên trường trong Term ctors sẽ là vấn đề, nhưng Lucene nên ném một ngoại lệ phàn nàn về điều đó, vì vậy đoán đó không phải là vấn đề thực sự ở đây. Có thể là phiên bản Lucene tại thời điểm này được viết đã không phàn nàn về các lĩnh vực không phù hợp trong SpanNears, vì vậy có lẽ đáng nói đến.

Điều này dường như làm việc với tôi:

SpanQuery termsInSentence = new SpanNearQuery(
    new SpanQuery[] { 
     new SpanTermQuery(new Term ("text", "red")), 
     new SpanTermQuery(new Term ("text", "green")), 
     new SpanTermQuery(new Term ("text", "blue")), 
    }, 
    9999, 
    false 
); 

SpanQuery nextSentence = new SpanTermQuery(new Term ("text", MY_SPECIAL_SENTENCE_TOKEN)); 

SpanQuery notInNextSentence = new SpanNotQuery(termsInSentence,nextSentence); 

Theo như nơi để chia câu, thay vì sử dụng phương pháp regex ngây thơ, tôi sẽ cố gắng sử dụng java.text.Breakiterator. Nó không hoàn hảo, nhưng nó làm một công việc khá tốt.

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