(轉)Lucene PhraseQuery、SpanQuery和PhrasePrefixQuery

原文:http://www.blogjava.net/persister/archive/2009/07/14/286634.htmlhtml

PhraseQuery使用位置信息來進行相關查詢,好比TermQuery使用「咱們」和「祖國」進行查詢,那麼文檔中含有這兩個詞的全部記錄都會被查詢出來。可是有一種狀況,咱們可能須要查詢「咱們」和「中國」之間只隔一個字和兩個字或者兩個字等,而不是它們之間字距相差十萬八千里,就可使用PhraseQuery。好比下面的狀況:
    doc.add(Field.Text("field", "the quick brown fox jumped over the lazy dog"));
那麼:
    String[] phrase = new String[] {"quick", "fox"};
    assertFalse("exact phrase not found", matched(phrase, 0));
    assertTrue("close enough", matched(phrase, 1));
multi-terms:
    assertFalse("not close enough", matched(new String[] {"quick", "jumped", "lazy"}, 3));
    assertTrue("just enough", matched(new String[] {"quick", "jumped", "lazy"}, 4));
    assertFalse("almost but not quite", matched(new String[] {"lazy", "jumped", "quick"}, 7));
    assertTrue("bingo", matched(new String[] {"lazy", "jumped", "quick"}, 8));

數字表示slop,經過以下方式設置,表示按照順序從第一個字段到第二個字段之間間隔的term個數。
    query.setSlop(slop);java

順序很重要:
    String[] phrase = new String[] {"fox", "quick"};
assertFalse("hop flop", matched(phrase, 2));
assertTrue("hop hop slop", matched(phrase, 3));

原理以下圖所示:


對於查詢關鍵字quick和fox,只須要fox移動一個位置便可匹配quick brown fox。而對於fox和quick這兩個關鍵字
須要將fox移動三個位置。移動的距離越大,那麼這項記錄的score就越小,被查詢出來的可能行就越小了。

SpanQuery利用位置信息查詢更有意思的查詢:

SpanQuery type         Description
SpanTermQuery         Used in conjunction with the other span query types. On its own, it’s
                                        functionally equivalent to TermQuery.
SpanFirstQuery         Matches spans that occur within the first part of a field.
SpanNearQuery         Matches spans that occur near one another.
SpanNotQuery         Matches spans that don’t overlap one another.
SpanOrQuery             Aggregates matches of span queries.

SpanFirstQuery:To query for spans that occur within the first n positions of a field, use Span-FirstQuery.



quick = new SpanTermQuery(new Term("f", "quick"));
brown = new SpanTermQuery(new Term("f", "brown"));
red = new SpanTermQuery(new Term("f", "red"));
fox = new SpanTermQuery(new Term("f", "fox"));
lazy = new SpanTermQuery(new Term("f", "lazy"));
sleepy = new SpanTermQuery(new Term("f", "sleepy"));
dog = new SpanTermQuery(new Term("f", "dog"));
cat = new SpanTermQuery(new Term("f", "cat"));

SpanFirstQuery sfq = new SpanFirstQuery(brown, 2);
assertNoMatches(sfq);
sfq = new SpanFirstQuery(brown, 3);
assertOnlyBrownFox(sfq);

SpanNearQuery:

彼此相鄰的跨度函數

      首先,強調一下PhraseQuery對象,這個對象不屬於跨度查詢類,但能完成跨度查詢功能。ui

      匹配到的文檔所包含的項一般是彼此相鄰的,考慮到原文檔中在查詢項之間可能有一些中間項,或爲了能查詢倒排的項,PhraseQuery設置了slop因子,可是這個slop因子指2個項容許最大間隔距離,不是傳統意義上的距離,是按順序組成給定的短語,所須要移動位置的次數這表示PhraseQuery是必須按照項在文檔中出現的順序計算跨度的,如quick brown fox爲文檔,則quick fox2個項的slop爲1,quick向後移動一次.而fox quick須要quick向後移動3次,因此slop爲3spa

      其次,來看一下SpanQuery的子類SpanTermQuery。.net

      它能跨度查詢,而且不必定非要按項在文檔中出現的順序,能夠用一個獨立的標記表示查詢對象必須按順序,或容許按倒過來的順序完成匹配。匹配的跨度也不是指移動位置的次數,是指從第一個跨度的起始位置到最後一個跨度的結束位置。3d

      在SpanNearQuery中將SpanTermQuery對象做爲SpanQuery對象使用的效果,與使用PharseQuery的效果很是類似。在SpanNearQuery的構造函數中的第三個參數爲inOrder標誌,設置這個標誌,表示按項在文檔中出現的順序倒過來的順序。htm

      如:the quick brown fox jumps over the lazy dog這個文檔對象

      public void testSpanNearQuery() throws Exception{blog

           SpanQuery[] quick_brown_dog=new SpanQuery[]{quick,brown,dog};

           SpanNearQuery snq=new SpanNearQuery(quick_brown_dog,0,true);//按正常順序,跨度爲0,對三個項進行查詢

           assertNoMatches(snq);//沒法匹配

           SpanNearQuery snq=new SpanNearQuery(quick_brown_dog,4,true);//按正常順序,跨度爲4,對三個項進行查詢

           assertNoMatches(snq);//沒法匹配

           SpanNearQuery snq=new SpanNearQuery(quick_brown_dog,4,true);//按正常順序,跨度爲5,對三個項進行查詢

           assertOnlyBrownFox(snq);//匹配成功    

           SpanNearQuery snq=new SpanNearQuery(new SpanQuery[]{lazy,fox},3,false);//按相反順序,跨度爲3,對三個項進行查詢

           assertOnlyBrownFox(snq);//匹配成功   

           //下面使用PhraseQuery進行查詢,由於是按順序,因此lazy和fox必需要跨度爲5

           PhraseQuery pq=new PhraseQuery();

           pq.add(new Term("f","lazy"));

           pq.add(new Term("f","lazy"));

           pq.setslop(4);

           assertNoMatches(pq);//跨度4沒法匹配

           //PharseQuery,slop因子爲5

           pq.setSlop(5);

           assertOnlyBrownFox(pq);          

      }3.PhrasePrefixQuery 主要用來進行同義詞查詢的:    IndexWriter writer = new IndexWriter(directory, new WhitespaceAnalyzer(), true);    Document doc1 = new Document();    doc1.add(Field.Text("field", "the quick brown fox jumped over the lazy dog"));    writer.addDocument(doc1);    Document doc2 = new Document();    doc2.add(Field.Text("field","the fast fox hopped over the hound"));    writer.addDocument(doc2);    PhrasePrefixQuery query = new PhrasePrefixQuery();    query.add(new Term[] {new Term("field", "quick"), new Term("field", "fast")});    query.add(new Term("field", "fox"));    Hits hits = searcher.search(query);    assertEquals("fast fox match", 1, hits.length());    query.setSlop(1);    hits = searcher.search(query);    assertEquals("both match", 2, hits.length());

相關文章
相關標籤/搜索