- 自己動手寫分布式搜索引擎
- 羅剛
- 420字
- 2020-11-28 15:52:51
3.3.13 關(guān)鍵詞高亮顯示
因為搜索出來的文檔內(nèi)容可能比較長,所以不僅要檢索出命中的文本,還要提供查詢詞在文本中出現(xiàn)的位置,方便用戶直接看到想要找的信息。最終高亮顯示的是一個片段(包含高亮詞),而不是一個完整的列值。將來的瀏覽器應(yīng)該可以支持顯示全文的同時,先定位到查詢詞所在的位置。
在搜索結(jié)果中一般都有和用戶搜索關(guān)鍵詞相關(guān)的摘要。關(guān)鍵詞一般都會高亮顯示。從實現(xiàn)上說,就是把要突出顯示的關(guān)鍵詞前加上<B>標(biāo)簽,關(guān)鍵詞后加上</B>標(biāo)簽。Lucene的highlighter包可以做到這一點。
Lucene有兩個高亮顯示的實現(xiàn):一個是org.apache.lucene.search.highlight;還有一個是org.apache.lucene.search.vectorhighlight。下面是使用org.apache.lucene.search.highlight的例子:
doSearching("汽車"); //使用一個查詢初始化Highlighter對象 Highlighter highlighter = new Highlighter(new QueryScorer(query)); //設(shè)置分段顯示的文本長度 highlighter.setTextFragmenter(new SimpleFragmenter(40)); //設(shè)置最多顯示的段落數(shù)量 int maxNumFragmentsRequired = 2; for (int i = 0; i < hits.length(); i++) { //取得索引庫中存儲的原始文本 String text = hits.doc(i).get(FIELD_NAME); TokenStream tokenStream=analyzer.tokenStream(FIELD_NAME, new StringReader(text)); //取得關(guān)鍵詞加亮后的結(jié)果 String result = highlighter.getBestFragments(tokenStream, text, maxNumFragmentsRequired, "..."); System.out.println("\t" + result); }
QueryScorer()設(shè)置查詢的query,這里還可以加上對字段列的限制,比如只對body條件的term高亮顯示,可以使用new QueryScorer(query, “body”)。對于模糊匹配,需要先找出要高亮顯示的詞。可以使用SpanScorer和SimpleSpanFragmenter,或者使用QueryScorer和SimpleFragmenter。
使用SpanScorer和SimpleSpanFragmenter生成高亮段落的代碼如下:
TokenStream stream = TokenSources.getTokenStream(fieldName, fieldContents, analyzer); SpanScorer scorer = new SpanScorer(query, fieldName, new CachingTokenFilter(stream)); Fragmenter fragmenter = new SimpleSpanFragmenter(scorer, 100); Highlighter highlighter = new Highlighter(scorer); highlighter.setTextFragmenter(fragmenter); String[] fragments = highlighter.getBestFragments(stream, fieldContents, 5);
為了實現(xiàn)關(guān)鍵詞高亮顯示,必須知道關(guān)鍵詞在文本中的位置。對英文來說,可以在搜索的時候?qū)崟r切分出位置。但是中文分詞的速度一般來說相對慢很多。在Lucene1.4.3以后的版本中,TermVector支持保存Token.getPositionIncrement()和Token.startOffset() 以及Token.endOffset() 信息。利用Lucene中新增加的Token信息保存結(jié)果以后,就不需要為了高亮顯示而在運行時解析每篇文檔。為了實現(xiàn)一列的高亮顯示,索引的時候通過Field對象保存該位置信息。
//增加文檔時保存term位置信息 private void addDoc(IndexWriter writer, String text) throws IOException{ Document d = new Document(); Field f = new Field(FIELD_NAME, text , Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.WITH_POSITIONS_OFFSETS); d.add(f); writer.addDocument(d); } //利用term位置信息節(jié)省Highlight時間 void doStandardHighlights() throws Exception{ Highlighter highlighter =new Highlighter(this, new QueryScorer(query)); highlighter.setTextFragmenter(new SimpleFragmenter(20)); for (int i = 0; i < hits.length(); i++) { String text = hits.doc(i).get(FIELD_NAME); int maxNumFragmentsRequired = 2; String fragmentSeparator = "..."; TermPositionVector tpv = (TermPositionVector)reader.getTermFreqVector(hits.id(i), FIELD_NAME); TokenStream tokenStream=TokenSources.getTokenStream(tpv); String result = highlighter.getBestFragments( tokenStream, text, maxNumFragmentsRequired, fragmentSeparator); System.out.println("\t" + result); } }
最后把highlight包中的一個額外的判斷去掉。對于中文來說沒有明顯的單詞界限,所以下面這個判斷是錯誤的:
tokenGroup.isDistinct(token)
注意上面代碼中的highlighter.setTextFragmenter(new SimpleFragmenter(20)), SimpleFragmenter是一個最簡單的段落分割器,它把文章按20個字分成一個段落。這種方式簡單易行,但顯得比較初步。有時會有一些沒意義的符號出現(xiàn)在摘要的起始部分,例如逗號出現(xiàn)在摘要的開始位置。
RegexFragmenter是一個改進版本的段落分割器。它通過一個正則表達式匹配可能的熱點區(qū)域。但它是為英文定制的。我們可以讓它認(rèn)識中文的字符段。
protected static final Pattern textRE = Pattern.compile("[\\w\u4e00-\u9fa5]+");
這樣使用highlighter就變成了:
highlighter.setTextFragmenter(new RegexFragmenter(descLenth));
比如“我的媽媽”, Google搜索是這樣:“<em>我的</em> <em>媽媽</em>”。實際貌似Lucene都會變成“<em>我</em><em>的</em><em>媽媽</em>”,這樣對SEO(搜索引擎優(yōu)化)很不好。<em>標(biāo)簽算是權(quán)重很高的標(biāo)簽,這樣分使得頁面會降很低,因為詞都是分開的。另外,合并到一起,也省流量,對SEO有利。
不要高亮顯示太長的文本,因為這樣會影響搜索速度。
- 中文版3ds Max 2013-VRay效果圖制作從新手到高手
- 持續(xù)演進的Cloud Native:云原生架構(gòu)下微服務(wù)最佳實踐
- 中文版After Effects CC 2020完全自學(xué)一本通
- 中文版3ds Max 2016/VRay效果圖制作實戰(zhàn)基礎(chǔ)教程
- Hi!扁平化Photoshop扁平化用戶界面設(shè)計教程
- 跟儲君老師學(xué)Excel極簡思維
- Liferay User Interface Development
- After Effects CC 2019 影視后期特效合成案例教程
- PHP應(yīng)用開發(fā)與實踐
- Cinema 4D完全實戰(zhàn)技術(shù)手冊
- 3ds Max/MaxScript印象 腳本動畫制作基礎(chǔ)與應(yīng)用
- AutoCAD 2019中文版計算機輔助繪圖全攻略
- 邊做邊學(xué):平面廣告設(shè)計與制作(Photoshop 2020+Illustrator 2020·第3版·微課版)
- Jetpack Compose:Android全新UI編程
- Photoshop CS6完美創(chuàng)意設(shè)計:不一樣的圖像藝術(shù)處理