【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>
学完本课题,你应达成如下目标:
掌握分面搜索;
掌握搜索结果高亮用法
掌握查询建议用法
分面搜索
什么是分面搜索?
例子1:
想买一部手机,在电商网站的搜索框中输入手机,会得到什么?
我该如何选?
我想同时了解有哪些品牌、各品牌的商品量?
有哪些价格区间、各价格区间的商品量?
有哪些屏幕尺寸、每个价格区间的商品量?
例子2:
找工作搜索职位,输入 架构师
我想同时了解我感兴趣城市招聘架构师的岗位量?
我想同时了解各行业招聘架构师的岗位量?
分面搜索:在搜索结果的基础上进行按指定维度的统计,以展示搜索结果的另一面信息。
分面搜索示例
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/browse
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内核上进分面查询:
1、指定按cat进行分面,测试sort、limit、mincount、prefix、missing 参数
2、增加按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内核上进分面查询: 1、按价格进行区间分面: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提供了高亮功能,只需我们解答以下问题:
1、哪些字段需要高亮处理?
2、如何高亮?
高亮参数说明
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>
<!-- 允许的最大编辑数(即最多多少个字符不同),可取值:1、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(以重新加载拼写检查字典)
拼写检查请求示例
1、请查看techproducts内核配置文件solrconfig.xml中的/spell请求处理器的配置。
2、尝试下面的查询请求,请看推荐结果在哪里,都有些什么推荐词。
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
思考:自动建议查询词提供的是某字段的索引词项,建议内容可不可以是某个字段的值(如标题、名称),这样查询的精确度更高?
来源:oschina
链接:https://my.oschina.net/u/3728166/blog/3017824