書名: 自己動手寫分布式搜索引擎作者名: 羅剛本章字數: 1450字更新時間: 2020-11-28 15:52:49
3.3.7 跨度查詢
若查詢詞是“吃飯”,而文檔中出現了“吃完飯”這樣的詞。把查詢詞和文檔都按最小粒度分詞,分成“吃”和“飯”兩個詞。文檔中的這兩個詞雖然不是連續出現,但只間隔了一個詞。
近似查詢假設同時查詢的幾個詞之間的匹配點很近,則這樣的文檔可能也是要查找的。匹配詞在文檔中的位置信息用跨度(Spans)描述。抽象類Spans封裝了一次匹配的文檔和位置信息。span是一個<文檔編號,開始位置,結束位置>的三元組。
Spans的接口定義如下:
boolean next() //移動到下一個匹配的文檔 boolean skipTo(int target)//跳到指定的文檔 int doc()//當前的文檔編號 int start()//匹配區域的開始位置 int end() //匹配區域的結束位置
TermSpans是Spans的具體子類。
SpanQuery稱為跨度查詢,用于查詢多個詞時考慮幾個詞在文檔中的匹配位置。SpanQuery和PhraseQuerys或者MultiPhraseQuerys很相似,因為都是通過位置限制匹配,但是SpanQuery更靈活。
SpanNearQuery用來查詢在比較近的區域內出現的多個查詢詞。例如,下面這個查詢既可以匹配“吃飯”,又可以匹配“吃完飯”。
new SpanNearQuery(new SpanQuery[] { new SpanTermQuery(new Term(FIELD, "吃")), //第1個詞 new SpanTermQuery(new Term(FIELD, "飯"))}, //第2個詞 1, //在1個位置以內 true); //有序
SpanTermQuery是一個最基礎的跨度搜索實現類,因為可以通過它得到一個詞的位置信息。在SpanNearQuery的構造方法中可以指定一些查詢詞需要在多近的區域出現。
同樣的幾個詞在一起,但是如果順序不一樣,意思可能就不一樣。例如,“花的中間”與“中間的花”意義就不一樣,類似的例子還有“媽媽愛自己的兒女”和“兒女愛自己的媽媽”。所以,SpanNearQuery有一個參數表示是否要求按數組中的順序匹配。
例如,需要查找lucene和doug在5個位置以內,doug在lucene之后,也就是說,詞出現的順序是需要考慮的。可以使用如圖3-11所示的SpanNearQuery。

圖3-11 SpanNearQuery
SpanQuery[] baseQueries = new SpanQuery[] { new SpanTermQuery(new Term(FIELD, "lucene")), new SpanTermQuery(new Term(FIELD, "doug"))}; //這里的true表示詞必須按數組中的順序出現在文檔中 new SpanNearQuery(baseQueries, 5, true);
在這個例子中,lucene和doug的間隔在3以內,也就是間隔了3個詞。
SpanNearQuery會查找互相在給定距離內的一些數量的SpanQuery。可以指定span是按順序或者不按順序查詢。SpanNearQuery根據SpanQuery對象組成的數組來構建。因為SpanTermQuery是SpanQuery的子類,所以可以根據SpanTermQuery構造出SpanNearQuery。
SpanNearQuery構造方法接收一個SpanQuery數組。span之間的距離,一個布爾值表明是否要求按SpanQuery數組中的順序出現。下面是另一個嵌套的例子。這次,查找doug在lucene之后的5個間隔內,而hadoop在lucene → doug之后的4個間隔內,如圖3-12所示。

圖3-12 嵌套的SpanNearQuery
SpanNearQuery spanNear = new SpanNearQuery(new SpanQuery[] { new SpanTermQuery(new Term(FIELD, "lucene")), new SpanTermQuery(new Term(FIELD, "doug"))}, 5, true); new SpanNearQuery(new SpanQuery[] { spanNear, new SpanTermQuery(new Term(FIELD, "hadoop"))}, 4, true);
有些列,例如標題,頭幾個詞可能更重要,可以使用SpanFirstQuery限定只查詢前幾個詞。例如,查找名稱以“玩具”開頭的產品。
SpanTermQuery toy = new SpanTermQuery(new Term("title", "玩具")); SpanFirstQuery first = new SpanFirstQuery(toy, 1); //限定在頭一個位置出現
可以把SpanFirstQuery看成是SpanNearQuery的特例,第一個詞是一個虛擬的開始詞,從第二個詞開始才是真正的匹配詞。
例如,有兩個文檔“I love Lucene”和“Lucene is nice”,想要能夠查詢Lucene出現在最開始的文檔,也就是匹配正則表達式“^Lucene .*”的文檔。
SpanTermQuery lucene = new SpanTermQuery(new Term("title", "Lucene")); SpanFirstQuery first = new SpanFirstQuery(lucene, 1); //限定在頭一個位置出現
SpanRegexQuery使用標準的正則表達式語法。例如,查詢年:2000, 2001, 2002, ..., 2009。
SpanRegexQuery srq = new SpanRegexQuery(new Term("year", "200.? "));
SpanNotQuery包含必須滿足的SpanQuery和必須排除的SpanQuery。例如,要查找Microsoft Windows,但是不匹配Microsoft Windows之后的文檔是大寫的,偽代碼如下:
SpanNot: include: SpanNear(in-order=true, slop=0): SpanTerm: "Microsoft" SpanTerm: "Windows" exclude: SpanNear(in-order=true, slop=0): SpanTerm: "Microsoft" SpanTerm: "Windows" SpanRegex: "^\\p{Lu}.*"
實際的代碼:
SpanNearQuery includeQuery = new SpanNearQuery(new SpanQuery[] { new SpanTermQuery(new Term(FIELD, "Microsoft")), new SpanTermQuery(new Term(FIELD, "Windows"))}, 0, true); SpanRegexQuery upperCaseQuery = new SpanRegexQuery( new Term(FIELD, "^\\p{Lu}.*")); SpanNearQuery excludeQuery = new SpanNearQuery(new SpanQuery[] { new SpanTermQuery(new Term(FIELD, "Microsoft")), new SpanTermQuery(new Term(FIELD, "Windows")), upperCaseQuery }, 0, true);
若想查找包含“喜歡”一詞,并且在其前面沒有“不”字的文檔。可以這樣:
SpanNotQuery(like, SpanNearQuery(not, like))
再擴展出同類查詢詞,也就是:
SpanNotQuery( SpanOrQuery(喜歡,愛...) SpanNearQuery( SpanOrQuery(不) SpanOrQuery(喜歡,愛...) ) )
SpanOrQuery可以匹配符合任何一個條件的文檔。
SpanTermQuery term1 = new SpanTermQuery(new Term("field", "thirty")); SpanTermQuery term2 = new SpanTermQuery(new Term("field", "three")); SpanNearQuery near1 = new SpanNearQuery(new SpanQuery[] {term1, term2}, 0, true); SpanTermQuery term3 = new SpanTermQuery(new Term("field", "forty")); SpanTermQuery term4 = new SpanTermQuery(new Term("field", "seven")); SpanNearQuery near2 = new SpanNearQuery(new SpanQuery[] {term3, term4}, 0, true); SpanOrQuery query = new SpanOrQuery(new SpanQuery[] {near1, near2});
例如,說一個人壞透了,用“頭上長瘡,腳下流膿”來形容。這個條件可以這樣描述:
SpanAndQuery( SpanFirstQuery(瘡) SpanLastQuery(膿) )
SpanAndQuery和SpanLastQuery都還沒有現成的實現例子。
- Illustrator實例教程:Illustrator 2021(電子活頁微課版)
- Scratch 1.4: Beginner’s Guide
- SolidWorks 2008機械設計一冊通
- Lightroom Classic完全自學一本通
- 中文版Photoshop 2020基礎教程
- Oracle Siebel CRM 8 User Management: LITE
- iPhone JavaScript Cookbook
- CMS Design Using PHP and jQuery
- Oracle Warehouse Builder 11g: Getting Started
- After Effects 2022從入門到精通
- Microsoft Azure: Enterprise Application Development
- Mastering Zabbix
- 中文版Photoshop CS6完全自學手冊(超值版)
- JBoss Drools Business Rules
- Python 3 Web Development Beginner's Guide