문제

{ 'foo', 'bar', 'baz'} 문서가 주어지면 Spannearquery를 토큰 { 'baz', 'extra'}와 일치시키고 싶습니다.

그러나 이것은 실패합니다.

이걸 어떻게 가나 요?

다음 결과와 함께 샘플 테스트 (Lucene 2.9.1 사용) :

  • GivensingLematch- 패스
  • GiventWomatches- 패스
  • GiventhReematches- 패스
  • givensinglematch_andextraterm- 실패

...

import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.spans.SpanNearQuery;
import org.apache.lucene.search.spans.SpanQuery;
import org.apache.lucene.search.spans.SpanTermQuery;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.Version;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;

public class SpanNearQueryTest {

    private RAMDirectory directory = null;

    private static final String BAZ = "baz";
    private static final String BAR = "bar";
    private static final String FOO = "foo";
    private static final String TERM_FIELD = "text";

    @Before
    public void given() throws IOException {
        directory = new RAMDirectory();
        IndexWriter writer = new IndexWriter(
                directory,
                new StandardAnalyzer(Version.LUCENE_29),
                IndexWriter.MaxFieldLength.UNLIMITED);

        Document doc = new Document();
        doc.add(new Field(TERM_FIELD, FOO, Field.Store.NO, Field.Index.ANALYZED));
        doc.add(new Field(TERM_FIELD, BAR, Field.Store.NO, Field.Index.ANALYZED));
        doc.add(new Field(TERM_FIELD, BAZ, Field.Store.NO, Field.Index.ANALYZED));

        writer.addDocument(doc);
        writer.commit();
        writer.optimize();
        writer.close();
    }

    @After
    public void cleanup() {
        directory.close();
    }

    @Test
    public void givenSingleMatch() throws IOException {

        SpanNearQuery spanNearQuery = new SpanNearQuery(
                new SpanQuery[] {
                        new SpanTermQuery(new Term(TERM_FIELD, FOO))
                }, Integer.MAX_VALUE, false);

        TopDocs topDocs = new IndexSearcher(IndexReader.open(directory)).search(spanNearQuery, 100);

        Assert.assertEquals("Should have made a match.", 1, topDocs.scoreDocs.length);
    }

    @Test
    public void givenTwoMatches() throws IOException {

        SpanNearQuery spanNearQuery = new SpanNearQuery(
                new SpanQuery[] {
                        new SpanTermQuery(new Term(TERM_FIELD, FOO)),
                        new SpanTermQuery(new Term(TERM_FIELD, BAR))
                }, Integer.MAX_VALUE, false);

        TopDocs topDocs = new IndexSearcher(IndexReader.open(directory)).search(spanNearQuery, 100);

        Assert.assertEquals("Should have made a match.", 1, topDocs.scoreDocs.length);
    }

    @Test
    public void givenThreeMatches() throws IOException {

        SpanNearQuery spanNearQuery = new SpanNearQuery(
                new SpanQuery[] {
                        new SpanTermQuery(new Term(TERM_FIELD, FOO)),
                        new SpanTermQuery(new Term(TERM_FIELD, BAR)),
                        new SpanTermQuery(new Term(TERM_FIELD, BAZ))
                }, Integer.MAX_VALUE, false);

        TopDocs topDocs = new IndexSearcher(IndexReader.open(directory)).search(spanNearQuery, 100);

        Assert.assertEquals("Should have made a match.", 1, topDocs.scoreDocs.length);
    }

    @Test
    public void givenSingleMatch_andExtraTerm() throws IOException {

        SpanNearQuery spanNearQuery = new SpanNearQuery(
                new SpanQuery[] {
                        new SpanTermQuery(new Term(TERM_FIELD, BAZ)),
                        new SpanTermQuery(new Term(TERM_FIELD, "EXTRA"))
                },
                Integer.MAX_VALUE, false);

        TopDocs topDocs = new IndexSearcher(IndexReader.open(directory)).search(spanNearQuery, 100);

        Assert.assertEquals("Should have made a match.", 1, topDocs.scoreDocs.length);
    }
}
도움이 되었습니까?

해결책

SpannearQuery를 사용하면 서로 특정 거리 내에있는 용어를 찾을 수 있습니다.

예제 ( http://www.lucidimagination.com/blog/2009/07/18/the-spanquery/):

Doug가 Lucene (주문 문제)을 따르는 Doug의 5 위치 내에서 Lucene을 찾고 싶다고 가정 해 봅시다. 다음과 같은 범위를 사용할 수 있습니다.

new SpanNearQuery(new SpanQuery[] {
  new SpanTermQuery(new Term(FIELD, "lucene")),
  new SpanTermQuery(new Term(FIELD, "doug"))},
  5,
  true);

Alt Text http://www.lucidimagination.com/blog/wp-content/uploads/2009/07/spanquery-dia1.png

이 샘플 텍스트에서 Lucene은 Doug의 3 세 이내입니다.

그러나 예를 들어, 내가 볼 수있는 유일한 일치는 귀하의 쿼리와 대상 문서에 "CD"가 있다는 것입니다 (그리고 모든 용어가 단일 필드에 있다는 가정을하고 있습니다). 이 경우 특수 쿼리 유형을 사용할 필요가 없습니다. 표준 메커니즘을 사용하면 동일한 필드에 동일한 용어를 포함한다는 사실에 따라 0이 아닌 가중치를 얻게됩니다.

편집 3 - 최신 의견에 대한 응답으로 답은 사용할 수 없다는 것입니다. SpanNearQuery 문서의 여러 용어가 서로 특정 수의 장소 내에서 발생하는지 여부를 찾는 것 외에는 다른 일을하는 것입니다. 특정 사용 사례 / 예상 결과가 무엇인지 알 수는 없습니다 (자유롭게 게시하십시오). 마지막 경우 하나 이상 ( "BAZ", "Extra")이 문서, a BooleanQuery 잘 작동합니다.

편집 4 - 이제 당신은 당신의 유스 케이스를 게시 했으므로, 당신이 무엇을하고 싶은지 이해합니다. 다음은 할 수있는 방법입니다. BooleanQuery 위에서 언급했듯이 원하는 개별 용어와 SpanNearQuery, 그리고 SpanNearQuery.

따라서 텍스트 형식의 쿼리는 다음과 같습니다.

BAZ OR EXTRA OR "BAZ EXTRA"~100^5

(예로서 - 이것은 "baz"또는 "extra"를 포함하는 모든 문서와 일치하지만 "baz"와 "extra가 서로 100 곳 내에서 엑스트라가 발생하는 문서에 더 높은 점수를 할당하고, 위치를 조정하고 이 예제는 Solr 요리 책에서 나온 것이므로 루센에서 구문 분석하지 못하거나 바람직하지 않은 결과를 줄 수 있습니다. 다음 섹션에서는 API를 사용하여이를 구축하는 방법을 보여주기 때문에 괜찮습니다).

프로그래밍 방식으로 다음과 같이 구성합니다.

Query top = new BooleanQuery();

// Construct the terms since they will be used more than once
Term bazTerm = new Term("Field", "BAZ");
Term extraTerm = new Term("Field", "EXTRA");

// Add each term as "should" since we want a partial match
top.add(new TermQuery(bazTerm), BooleanClause.Occur.SHOULD);
top.add(new TermQuery(extraTerm), BooleanClause.Occur.SHOULD);

// Construct the SpanNearQuery, with slop 100 - a document will get a boost only
// if BAZ and EXTRA occur within 100 places of each other.  The final parameter means
// that BAZ must occur before EXTRA.
SpanNearQuery spanQuery = new SpanNearQuery(
                              new SpanQuery[] { new SpanTermQuery(bazTerm), 
                                                new SpanTermQuery(extraTerm) }, 
                              100, true);

// Give it a boost of 5 since it is more important that the words are together
spanQuery.setBoost(5f);

// Add it as "should" since we want a match even when we don't have proximity
top.add(spanQuery, BooleanClause.Occur.SHOULD);

도움이되기를 바랍니다! 앞으로, 당신이 기대하는 결과를 정확하게 게시하여 시작하려고 노력하십시오. 그것이 당신에게 분명하더라도 독자에게는 그렇지 않을 수도 있고, 명백한 것은 여러 번 앞뒤로 갈 필요가 없습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top