學完本課題,你應達成以下目標:html
掌握分面搜索;
掌握搜索結果高亮用法
掌握查詢建議用法java
分面搜索算法
什麼是分面搜索?apache
例子1:
想買一部手機,在電商網站的搜索框中輸入手機,會獲得什麼?
我該如何選?
我想同時瞭解有哪些品牌、各品牌的商品量?
有哪些價格區間、各價格區間的商品量?
有哪些屏幕尺寸、每一個價格區間的商品量?架構
例子2:
找工做搜索職位,輸入 架構師
我想同時瞭解我感興趣城市招聘架構師的崗位量?
我想同時瞭解各行業招聘架構師的崗位量?ide
分面搜索:在搜索結果的基礎上進行按指定維度的統計,以展現搜索結果的另外一面信息。post
分面搜索示例測試
http://sou.zhaopin.com/jobs/searchresult.ashx?jl=%E9%95%BF%E6%B2%99&kw=%E6%9E%B6%E6%9E%84%E5%B8%88&p=1&isadv=0網站
http://localhost:8983/solr/techproducts/browseui
Solr中支持的分面查詢
字段分面
執行搜索時,根據查詢請求返回特定分面字段中找到的惟一值以及找到的文檔數。
通用查詢參數
facet:true/false 對當前搜索是否啓用分面
facet.query:指定一個額外的分面查詢語句
字段分面查詢參數
facet.field:指定對哪一個字段進行分面計算。該參數能夠屢次指定以返回多個字段方面。字段需是索引字段。
facet.sort:分面結果的排序方式:count:根據統計數量排,index: 索引的詞典順序
facet.limit:肯定每一個分面返回多少個惟一分面值。可取值:整數>=-1,-1表示不限制,默認100。
facet.offset:對分面值進行分頁,指定頁偏移。 >=0 默認0。
facet.prefix:指定限制字段分面值必須以xxx開頭,用以篩選分面值。
facet.missing:true/false,是否在分面字段中返回全部不包含值(值爲缺失)的文檔計數。
facet.mincount:指定分面結果中的分面值的統計數量>=mincount的才返回。
sort、limit、offset、prefix、missing、mincount 可根據字段指定: f.filedname.facet.sort=count
字段分面-練習
在techproduct內核上進分面查詢:
一、指定按cat進行分面,測試sort、limit、mincount、prefix、missing 參數
二、增長按manu_exact 進行分面,它只返回量前5的
區間分面
區間分面將數值或時間字段值分紅一些區間段,按區間段進行統計。
區間分面查詢參數
facet.range:指定對哪一個字段計算區間分面。可屢次用該參數指定多個字段。 facet.range=price&facet.range=age facet.range.start:起始值 f.price.facet.range.start=0.0&f.age.facet.range.start=10 f.lastModified_dt.facet.range.start=NOW/DAY-30DAYS facet.range.end:結束值 f.price.facet.range.end=1000.0&f.age.facet.range.start=99 f.lastModified_dt.facet.range.end=NOW/DAY+30DAYS facet.range.gap:間隔值,建立子區間。對於數值字段,間隔值是數值,對於時間字段,用時間數學表達式(如+1DAY、+2MONTHS、+1HOUR等) f.price.facet.range.gap=100&f.age.facet.range.gap=10 f.lastModified_dt.facet.range.gap=+1DAY facet.range.hardend:若是間隔在下限和上限之間不是均勻分佈,最後一個區間的大小要小於其餘區間,當該參數爲true時,最後區間的最大值就是上限值,若是爲false,則最後區間會自動上擴,與其餘區間等長。 facet.range.other 區間外的值是否統計,可選值: before: 統計<start的文檔數 after:統計>end的文檔數 between:統計區間內的 none:不統計 all:統計before、after、between的數量 facet.range.include:區間的邊界是如何包含的,默認是包含下邊界值,不包含上邊界值 (最後一個區間包含) 。可選值: lower:全部區間包含下邊界 upper:全部區間包含上邊界 edge:第一個區間包含下邊界,最後一個區間包含上邊界。 outer:範圍前「before」 和 後 「after」的統計區間將包含範圍的下邊界、上邊界。即便範圍內的區間包含了上、下邊界。 all:選擇全部選項:lower、upper、edge、outer Facet.mincount 也可以使用。 注意:避免重複統計,不要同時選擇lower和upper、outer、all 可根據字段來指定: f.<fieldname>.facet.range.include
區間分面-練習
在techproduct內核上進分面查詢: 一、按價格進行區間分面:10~10000 每間隔500一個區間
查詢分面
直接經過facet.query參數指定查詢,來進行分面。
q=*:*&facet=true&facet.query=price:[* TO 5}&facet.query=price:[5 TO 10}&facet.query=price:[10 TO 20}&facet.query=price:[20 TO 50}&facet.query=price:[50 TO *]
多級分面
pivot(Decision Tree)faceting:決策樹分面,又稱多級分面。如想看對搜中商品的按類別統計結果,在類別下又想看它的流行度構成。如:
圖書(10)
20(5)
10(5)
多級分面查詢參數
facet.pivot:指定分級字段,以逗號間隔。可多個facet.pivot參數指定多個分級分面。 facet.pivot=cat,popularity,inStock&facet.pivot=cat,inStock facet.pivot.mincount ;最少匹配文檔數,默認1。
http://localhost:8983/solr/techproducts/select?q=*:*&facet.pivot=cat,popularity,inStock&facet.pivot=popularity,cat&facet=true&facet.field=cat&facet.limit=5&facet.pivot.mincount=2
key
字段分面、區間分面的返回結果以字段名爲分面名,查詢分面是以查詢爲分面名,Key 關鍵字用來對分面項進行重命名。
q=*:*&facet=true&facet.query={!key="<5"}price:[* TO 5}&facet.query={!key="5-10"}price:[5 TO 10}&facet.query={!key="10-20"}price:[10 TO 20}&facet.query={!key="20-50"}price:[20 TO 50}&facet.query={!key=">50"}price:[50 TO *]&facet.field={!key="類別"}cat
什麼是搜索結果高亮 highlighting
在搜索結果展現中突出顯示搜索的關鍵字。下圖是在百度中輸入solr進行搜索的一條結果: solr是紅色高亮的
詢問:這個高亮是如何作到的?
Solr提供了高亮功能,只需咱們解答如下問題:
一、哪些字段須要高亮處理?
二、如何高亮?
高亮參數說明
hl:是否啓用高亮,默認false 。 hl.fl:要高亮處理的字段列表,能夠逗號、空格間隔,可使用通配符* hl.fl=name,feauts hl.tag.pre :高亮前綴,能夠是任意字符串,通常爲html、xml標籤,默認是<em> . (hl.simple.pre for the Original Highlighter) hl.tag.post:高亮後綴,默認是</em> hl.encoder :對字段值進行何種編碼處理,默認空,不作處理。若是指定爲html,會對字段值中的html字符進行編碼處理:如 < 轉爲 < & 轉爲 & hl.maxAnalyzedChars :對字段值的最多多少個字符進行高亮處理,默認值51200 個字符。 hl.snippets :一個字段中能夠有幾個高亮片斷,默認1。 hl.fragsize :高亮片斷的最大字符數,默認100,無上限。 hl.method:指定高亮的實現方式,可選值: unified, original, fastVector。默認是 original。 hl.q:若是你要高亮的詞不是主查詢中的詞,可經過此參數指定 hl.qparser:指定hl.q的查詢解析器 hl.requireFieldMatch:是否只是查詢用到的字段才高亮,默認false(hl.fl中指定的字段進行高亮處理)。 hl.usePhraseHighlighter:使用短語高亮,默認true。 hl.highlightMultiTerm:對於通配符查詢(多詞項查詢)是否高亮,默認true
高亮響應結果
{ "response": { "numFound": 1, "start": 0, "docs": [{ "id": "MA147LL/A", "name": "Apple 60 GB iPod with Video Playback Black", "manu": "Apple Computer Inc.", }] }, "highlighting": { "MA147LL/A": { "manu": [ "<em>Apple</em> Computer Inc." ] } } }
動手試試
http://localhost:8983/solr/techproducts/select?q=ipod&hl=true&hl.fl=name&hl.simple.pre=<span style='colr:red;font-size:20px'>&hl.simple.post=</span>
http://localhost:8983/solr/techproducts/select?q=ipod&hl=true&hl.fl=name&hl.tag.pre=<span style='colr:red;font-size:20px'>&hl.tag.post=</span>&hl.method=unified&wt=xml
拼寫檢查簡介
拼寫檢查解決因查詢詞拼寫錯誤致使搜索結果不佳的問題。
拼寫檢查是搜索引擎的一個重要特徵,幫助那些不想花時間構造查詢表達式的用戶,特別是移動環境中用戶。
針對用戶拼寫錯誤或關鍵字生僻,而搜索結果不佳,提供相近的詞建議。
拼寫檢查分析
拼寫檢查在什麼狀況下使用? 拼寫檢查組件應推薦什麼樣的詞? 拼寫檢查組件推薦的這些詞從哪來? 是否是全部相近的詞都推薦?
拼寫檢查組件配置
如需在查詢中使用拼寫檢查,咱們須要在solrconfig.xml中配置拼寫檢查組件,並在查詢請求處理器中配置使用拼寫檢查組件(每每做爲最後一個組件)。
拼寫檢查組件配置 查看一個內核的solrconfig.xml文件
<searchComponent name="spellcheck" class="solr.SpellCheckComponent"> <!-- 若有須要,可爲拼寫檢查指定單獨的分詞器(經過fieldType指定) --> <str name="queryAnalyzerFieldType">text_general</str> <!-- 在該組件中可定義多個拼寫檢查器(字典)--> <!-- a spellchecker built from a field of the main index --> <lst name="spellchecker"> <str name="name">default</str> <str name="field">text</str> <str name="classname">solr.DirectSolrSpellChecker</str> ... </lst> <!-- a spellchecker that can break or combine words. --> <lst name="spellchecker"> <str name="name">wordbreak</str> <str name="classname">solr.WordBreakSolrSpellChecker</str> <str name="field">name</str> ... </lst> </searchComponent>
一個拼寫檢查器就是一種拼寫檢查實現方式。由name、classname、field、其餘參數構成。 在一個組件中可定義拼寫檢查器(字典),供查詢處理器選擇使用(可同時選擇多個,推薦結果爲多個的執行結果的合併)。
Solr中提供的拼寫檢查實現類
IndexBasedSpellChecker 獨立拼寫檢查索引的實現方式
DirectSolrSpellChecker 使用solr主索引進行拼寫檢查
FileBasedSpellChecker 經過文件來提供拼寫檢查推薦詞的實現方式
WordBreakSolrSpellChecker 可靈活拆分、組合詞,基於主索引的實現方式。如多個英文單詞少了空格的狀況:solrspell checker,它能夠進行拆分、組合嘗試來推薦詞。
DirectSolrSpellChecker配置參數說明
<lst name="spellchecker"> <str name="name">default</str> <!-- 經過查詢哪一個字段的詞項來提供推薦詞 --> <str name="field">text</str> <str name="classname">solr.DirectSolrSpellChecker</str> <!-- 使用的拼寫檢查度量方法, 默認值internal 使用的是 levenshtein距離算法--> <str name="distanceMeasure">internal</str> <!-- 一個詞被認定爲推薦詞需知足的最低精確度。 0-1之間的浮點數,值越大精確度越高,推薦的詞越少 --> <float name="accuracy">0.5</float> <!-- 容許的最大編輯數(即最多多少個字符不一樣),可取值:一、2. --> <int name="maxEdits">2</int> <!-- 枚舉詞項來推薦時,要求的最低相同前綴字符數。--> <int name="minPrefix">1</int> <!-- 返回的最大推薦詞數。默認5 --> <int name="maxInspections">5</int> <!-- 要求的查詢詞項的最低字符數,默認4. 查詢的詞的字符數小於這個數就不進行拼寫檢查推薦。--> <int name="minQueryLength">4</int> <!-- 最大文檔頻率,高於該值的查詢詞不進行拼寫檢查的。能夠是百分比或絕對值 --> <float name="maxQueryFrequency">0.01</float> <!-- 要求推薦詞的文檔頻率高於這個值。能夠是百分比或絕對值 <float name="thresholdTokenFrequency">.01</float> --> </lst>
在查詢請求處理器中配置使用拼寫檢查
<requestHandler name="/spell" class="solr.SearchHandler" startup="lazy"> <lst name="defaults"> <str name="spellcheck.dictionary">default</str> <str name="spellcheck.dictionary">wordbreak</str> <str name="spellcheck">on</str> <str name="spellcheck.extendedResults">true</str> <str name="spellcheck.count">10</str> <str name="spellcheck.alternativeTermCount">5</str> <str name="spellcheck.maxResultsForSuggest">5</str> <str name="spellcheck.collate">true</str> <str name="spellcheck.collateExtendedResults">true</str> <str name="spellcheck.maxCollationTries">10</str> <str name="spellcheck.maxCollations">5</str> </lst> <arr name="last-components"> <str>spellcheck</str> </arr> </requestHandler>
拼寫檢查請求參數的默認值配置。將拼寫檢查組件加到最後。
拼寫檢查請求參數說明
spellcheck:是否使用拼寫檢查,true/false
spellcheck.q:進行拼寫檢查的查詢表達式,如未指定則使用q。
spellcheck.count:返回最多多少個推薦詞。默認1。
spellcheck.dictionary:指定使用的拼寫檢查器(字典)名,默認default,同時使用多個則屢次傳參指定。
spellcheck.accuracy:一個詞被認定爲推薦詞需知足的最低精確度。0-1之間的浮點數,值越大精確度越高,推薦的詞越少 spellcheck.onlyMorePopular:若是設置爲true,只返回比原始查詢詞文檔頻率更高的推薦詞。
spellcheck.maxResultsForSuggest:原始查詢匹配的文檔數低於多少時才應該進行推薦,這個參數指定這個閥值。
spellcheck.extendedResults:true,獲取推薦詞的其餘信息,如文檔頻次
拼寫檢查請求參數說明
spellcheck.collate:true、指示solr爲原始查詢生成一個最佳的校對查詢供用戶使用。如輸入「jawa class lording」,校對推薦"java class loading「
spellcheck.maxCollations:最多生成多少個校對查詢。默認1
spellcheck.build:true,則solr會爲拼寫檢查創建字典(如未創建)。directSolrSpellCheck不須要此選項。
spellcheck.reload:是否從新加載spellchecker(以從新加載拼寫檢查字典)
拼寫檢查請求示例
一、請查看techproducts內核配置文件solrconfig.xml中的/spell請求處理器的配置。
二、嘗試下面的查詢請求,請看推薦結果在哪裏,都有些什麼推薦詞。
http://localhost:8983/solr/techproducts/spell?df=text&spellcheck.q=delll+ultra+sharp&spellcheck=true&spellcheck.collateParam.q.op=AND&wt=xml
自動建議查詢詞
拼寫檢查是查詢後推薦,自動建議查詢詞則在用戶輸入查詢詞就根據用戶的輸入給出建議查詢詞,從最開始就避免拼寫錯誤,提供更好的用戶體驗,特別是在在移動設備上。
自動建議查詢詞-分析
是否須要一個單獨的請求處理器來提供建議查詢詞?
你以爲建議的查詢詞是怎麼來的?
能否基於拼寫檢查組件實現自動建議查詢詞?
自動建議查詢詞組件
Solr中能夠基於拼寫檢查組件實現自動建議查詢詞。也提供了專門的建議查詢詞組件solr.SuggestComponent。在techproducts示例的內核配置文件solrconfig.xml中配置有建議查詢詞組件和請求處理器,可直接參考。
自動建議查詢詞組件配置-示例
<searchComponent name="suggest" class="solr.SuggestComponent"> <!-- 能夠定義多個建議器 --> <lst name="suggester"> <!-- 建議器名稱 --> <str name="name">mySuggester</str> <!-- 建議字典的查找實現類,默認 JaspellLookupFactory --> <str name="lookupImpl">FuzzyLookupFactory</str> <!-- 建議字典的實現類,默認 HighFrequencyDictionaryFactory --> <str name="dictionaryImpl">DocumentDictionaryFactory</str> <!-- 基於哪一個字段來提供建議查詢詞 --> <str name="field">cat</str> <!-- 指定權重字段 --> <str name="weightField">price</str> <!-- 指定要使用的分詞器(經過fieldType) <str name="suggestAnalyzerFieldType">string</str> <!-- 是否在solr啓動時就構建字典 --> <str name="buildOnStartup">false</str> </lst> </searchComponent>
詳細參數、參數選項請參考: http://lucene.apache.org/solr/guide/7_3/suggester.html
自動建議查詢請求處理器配置-示例
<requestHandler name="/suggest" class="solr.SearchHandler" startup="lazy"> <lst name="defaults"> <str name="suggest">true</str> <str name="suggest.count">10</str> </lst> <arr name="components"> <str>suggest</str> </arr> </requestHandler> 只須要建議器這一個組件
建議查詢詞請求參數說明
suggest :是否使用建議查詢詞,true/false
suggest.q:進行建議查詢詞用的查詢表達式。
suggest.count:返回最多多少個推薦詞。
suggest.dictionary:指定使用的建議器(字典)名,必需。
suggest.build:true,構建建議字典索引,在初次請求時構建,後續請求不須要帶這個參數。
suggest.reload:是否從新加載建議查詢詞索引。
自動建議查詢請求-示例
http://localhost:8983/solr/techproducts/suggest?suggest=true&suggest.build=true&suggest.dictionary=mySuggester&suggest.q=elec
使用多重suggest.dictionary
http://localhost:8983/solr/techproducts/suggest?suggest=true&suggest.dictionary=mySuggester&suggest.dictionary=altSuggester&suggest.q=elec
思考:自動建議查詢詞提供的是某字段的索引詞項,建議內容可不能夠是某個字段的值(如標題、名稱),這樣查詢的精確度更高?