Solr 6.7学习笔记(04)-- Suggest
当我们使用baidu或者Google时,你输入很少的字符,就会自动跳出来一些建议选项,在Solr里,我们称之为Suggest,在solrconfig.xml里做一些简单的配置,即可实现这一功能。配置如下:
<searchComponent name="suggest" class="solr.SuggestComponent">
<lst name="suggester">
<str name="name">mySuggester</str>
<str name="lookupImpl">FuzzyLookupFactory</str>
<str name="dictionaryImpl">DocumentDictionaryFactory</str>
<str name="field">cat</str>
<str name="weightField">price</str>
<str name="suggestAnalyzerFieldType">string</str>
<str name="buildOnStartup">false</str>
</lst>
</searchComponent> <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>
元素 <searchComponent> 的属性说明:
name:指定searchComponent的名字。可以定义多个<searchComponent>,只要名字不一样。在<requestHandler> --> <arr name="components"> --> <str> 里的值是指用哪个<searchComponent>。
<lst name="suggester"> 的一些属性
| 属性 | 描述 |
| name | suggest的名字,用于区分多个suggest。在请求参数中加入suggest.dictionary=mySuggester来指定使用哪个suggester |
| lookupImpl | 查询实现类,表示如何在Suggestions 字典中找到分词(Term) |
| dictionaryImpl | 字典实现类,表示分词(Term)是如何存储Suggestion字典的 |
| field |
表示suggestion的内容是基于哪个字段的。这里设置的field的stored属性必须是True。这可以设置为一个copyField,这样suggetion 就可台基于多个字段了。 |
| sourceLocation | 当dictionaryImpl为 FileDictionaryFactory时,指定此值,表示字典文件的路径 |
| storeDir | 存储字典文件的位置 |
| buildOnCommit |
默认值false。表示仅当请求的URL中包含suggest.build=true 时,才会创建 lookup的data。 为true时,表示lookup的data将在soft-commit后重新创建。 当索引比较大,尤其soft-commit很频繁时,建议设置为FALSE。此时应该手动地在请求中加上suggest.build=true 去触发构建lookup data的动作 |
| buildOnOptimize | 同上。区别是上面是soft-commit时,这里是索引优化时 |
| buildOnStartup |
设置为true,表示Solr启动或者Core重新加载时,构建suggestions的data。如果没有指定参数(文档中并没有说是设置为false),如果在磁盘上找不 到lookup data,则suggester将会构建它。通常建议设置成false,通过buildOnCommit中提到的方法去构建lookup data。 |
在同一个<searchComponent>里面,可以定义多个suggester (name 必须不一样)。如:
<searchComponent name="suggest" class="solr.SuggestComponent">
<lst name="suggester">
<str name="name">fuzzySuggester</str>
<str name="lookupImpl">FuzzyLookupFactory</str>
<str name="dictionaryImpl">DocumentDictionaryFactory</str>
<str name="field">cat</str>
<str name="weightField">price</str>
<str name="suggestAnalyzerFieldType">string</str>
<str name="buildOnStartup">false</str>
</lst>
<lst name="suggester">
<str name="name">freeTextSuggester</str>
<str name="lookupImpl">FreeTextLookupFactory</str>
<str name="dictionaryImpl">DocumentDictionaryFactory</str>
<str name="field">cat</str>
<str name="weightField">price</str>
<str name="suggestAnalyzerFieldType">string</str>
<str name="buildOnStartup">false</str>
</lst>
</searchComponent>
定义多个Suggester后,我们可以在
1. <requestHandler>中指定使用哪个(或哪些)Suggester。如:
<requestHandler name="/suggest" class="solr.SearchHandler" startup="lazy" >
<lst name="defaults">
<str name="suggest">true</str>
<str name="suggest.count">10</str>
<str name="suggest.dictionary">freeTextSuggester</str>
<str name="suggest.dictionary">fuzzySuggester</str>
</lst>
<arr name="components">
<str>suggest</str>
</arr>
</requestHandler>
2. 使用Solrj 去连接Solr进行"/suggest" 查询时,可以指定如下参数:
SolrQuery params = new SolrQuery();
params.set("qt", "/suggest");
params.set("suggest", "true"); //启用Suggest
params.set("suggest.build", "true");
params.set("suggest.dictionary", "fuzzySuggester");
params.set("suggest.dictionary", "freeTextSuggester"); ...
3. 自己使用http去Get 时:
http://localhost:8983/solr/techproducts/suggest?suggest=true&suggest.dictionary=fuzzySuggester&suggest.dictionary=freeTextSuggester&wt=json&suggest.q=elec
在<requestHandler name="/suggest">中的<lst name="defaults">里可以设置如下一些suggest的默认属性,其值可被URL中相同的参数覆盖
| 参数 | 描述 |
| suggest | 肯定设置为true |
| suggest.dictionary | suggester 的名字,可能过上面3种方法设置 |
| suggest.q | 在页面上输入的值。 |
| suggest.count | Solr返回的建议的分词的数量 |
| suggest.cfq |
用于过滤suggestion的基于context field的 Context Filter Query。仅AnalyzingInfixLookupFactory 和 BlendedInfixLooupFactory 支持此属性,并且dictionaryImpl 必须是 Document*Dictionary |
| suggest.build | 如果为 true, 则会构建lookup data。通常不可能每次请求都去构建。使用情境见上面的buildOnCommit |
| suggest.reload | 为true时,重新加载 suggester index |
| suggest.buildAll | 为true时, 创建所有的suggester index。不明白和suggest.build有什么区别 |
| suggest.reloadAll | 为true时,重新加载所有suggester index。不明白和 reload有什么区别 |
在程序员的世界里,学习任何语言或者技术,光看书是没有用的。看的时候感觉都懂。实际做的时候就这也不会那也不会。还是得靠实践。于是自己动手做了一个文件及其内容搜索的小程序,以此来加强对Solr的认识。设置了一些field:filename, filetype, filesize, content。这些用来存储文件相关的信息,还有一个名为text的copyField,用于存储所有值,以便查询时只需指定一个field。定义如下:
<field name="filename" type="string" index="true" stored="true" />
<field name="filetype" type="string" index="true" stored="true" />
<field name="filepath" type="decent_path" index="true" stored="true" />
<field name="filetsize" type="tint" index="true" stored="true" />
<field name="content" type="text_general" index="false" stored="true" multiValues="true" />
<field name="text" type="text_general" index="true" stored="false" multiValues="true" /> <copyField source="filename" dest="text" />
<copyField source="filetype" dest="text" />
<copyField source="filesize" dest="text" />
<copyField source="filepath" dest="text" />
<copyField source="content" dest="text" />
使用suggester的时候遇到的一些问题:
1. 一开始,suggester的 field 设置的是 "text",我本想是让所有的信息都可以做为建议项。用的是FuzzyLoopupFactory,可是发现建议项一直是空。不知道是哪边出了问题,以为是copyField的问题,但是文档写了可以用copyField的。尝试把field设置成"filename",可以出现建议项了。又仔细读了一次文档,发现原来“text”的stored属性是false。改成true后,就成功了。
2. 另外,期间我也有把field 改成"content",它的stored值是true,indexed值是false。可是还是不能成功得到建议项。把indexed的值改成true,这时,content这个field的属性和"text"是一样的了,但是建议项一直为空!!上网搜了一下,网上也都是抄抄官方文档的内容,找不到原因。突然发现suggester里面有一个suggestAnalyzerFieldType的属性,其值为string (见本篇最开始部分的配置),再查了一下文档,发现这是AnalyzingLookupFactory里的一个属性,而FuzzyLookupFactory是继承AnalyzingLookupFactory的,这个属性指定的是查询和创建suggest时,字段的类型。“content”的字段类型是text_general,而我配置的是string,所以找不到建议项。改成text_general后 -- 纳尼?还是查不到建议项。看了一下我的程序的日志,发现是有建议项的,只不过建议的内容是整个文件的内容,太长了。可能是前端jQuery的suggest组件会把过长的建议项删除。因此UI 上看不到。但是后台确实是有建议项的。注意:输入的内容必须是整个文件内容的开始字符。
3. 期间我也不小心索引了一个图片文件,不是文本的文件。结果查询时,抛了下面的exception。去掉这个图片的索引后就好了。
Caused by: java.lang.StackOverflowError
at org.apache.lucene.util.automaton.Operations.topoSortStatesRecurse(Operations.java:1288)
at org.apache.lucene.util.automaton.Operations.topoSortStatesRecurse(Operations.java:1293)
at org.apache.lucene.util.automaton.Operations.topoSortStatesRecurse(Operations.java:1293)
其实我想实现的Suggest是:如果有下面的一段文本,我在页面的搜索框里输入:man,会自动列出 manager,management和mana三个选项。
The manager of this management company is Mana.
但是上面配置的FuzzyLookupFactory,并不能实现这一需求。把suggester改成FreeTextLookupFactory,可以实现此需求。
<searchComponent name="suggest" class="solr.SuggestComponent">
<lst name="suggester">
<str name="name">mySuggester</str>
<str name="lookupImpl">FreeTextLookupFactory</str>
<str name="dictionaryImpl">DocumentDictionaryFactory</str>
<str name="field">content</str>
<str name="weightField">content</str>
<str name="suggestFreeTextAnalyzerFieldType">text-general</str>
<str name="buildOnStartup">false</str>
<str name="buildOnCommit">true</str>
</lst>
</searchComponent>
上一篇:
Solr 6.7学习笔记(02)-- 配置文件 managed-schema (schema.xml) -- 样例(6)
Solr 6.7学习笔记(04)-- Suggest的更多相关文章
- Solr 6.7学习笔记(02)-- 配置文件 managed-schema (schema.xml) - filter(5)
自定义fieldType时,通常还会用到filter.filter必须跟在tokenizer或其它filter之后.如: <fieldType> <analyzer> < ...
- 机器学习实战(Machine Learning in Action)学习笔记————04.朴素贝叶斯分类(bayes)
机器学习实战(Machine Learning in Action)学习笔记————04.朴素贝叶斯分类(bayes) 关键字:朴素贝叶斯.python.源码解析作者:米仓山下时间:2018-10-2 ...
- Solr 6.7学习笔记(02)-- 配置文件 managed-schema (schema.xml) -- 样例(6)
managed-schema 样例: <?xml version="1.0" encoding="UTF-8" ?> <!-- License ...
- Solr 6.7学习笔记(02)-- 配置文件 managed-schema (schema.xml)(3)
5. <fieldType> fieldType主要定义了一些字段类型,其name属性值用于前面<field>中的type属性的值.e.g. <fieldTyp ...
- SaToken学习笔记-04
SaToken学习笔记-04 如果有问题,请点击:传送门 角色认证 在sa-token中,角色和权限可以独立验证 // 当前账号是否含有指定角色标识, 返回true或false StpUtil.has ...
- Redis:学习笔记-04
Redis:学习笔记-04 该部分内容,参考了 bilibili 上讲解 Redis 中,观看数最多的课程 Redis最新超详细版教程通俗易懂,来自 UP主 遇见狂神说 10. Redis主从复制 1 ...
- Solr 6.7学习笔记(02)-- 配置文件 managed-schema (schema.xml)(1)
刚学Solr(版本6.7.0),新建一个core时,提示要求schema.xml文件,我找了半天也没在源码包中找到名为schema.xml的文件.这个版本其实用的是managed-schema文件,没 ...
- xml基础学习笔记04
今天继续xml学习,主要是:SimpleXML快速解析文档.xml与数组相互转换 .博客中只是简单的做一个学习记录.积累.更加详细的使用方法,可以查看php手册 1.SimpleXML快速解析文档 前 ...
- OpenCV 学习笔记 04 深度估计与分割——GrabCut算法与分水岭算法
1 使用普通摄像头进行深度估计 1.1 深度估计原理 这里会用到几何学中的极几何(Epipolar Geometry),它属于立体视觉(stereo vision)几何学,立体视觉是计算机视觉的一个分 ...
随机推荐
- 【linux】crontab的环境变量问题
今天遇到一个奇怪的问题,同样一个脚本,手动执行没问题,加入到crontab中,就出现无法运行的情况,第一反应是环境变量问题 环境说明: 操作系统:centos 用户:test用户通过sudo su切换 ...
- ZOJ - 3861 Valid Pattern Lock 【全排列】
题目链接 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3861 思路 先生成全排列,然后判断哪些情况不符合的,剔除就好了 ...
- P3968 [TJOI2014]电源插排
P3968 [TJOI2014]电源插排 线段树维护最长空区间及左端点位置,这个和$nlongn$的动态最大子序和差不多,就不多解释了 $n$较大哈希优化空间 My complete code: #i ...
- jsonp跨域请求,动态script标签实现跨域
1.什么是跨域 首先一个域名地址的组成是: http://www.xxx.com:8080/xxx/xxx.jsp 协议子域名主域名端口号请求资源地址 当协议.子域名.主域名.端口号中任意一个不相同时 ...
- css3线性渐变兼容
火狐浏览器: background:-moz-linear-gradient(top, red, rgba(0, 0, 255, 0.5)); 谷歌: .l6{background: -webkit- ...
- jsp和servlet的区别联系
jsp和servlet的区别联系 简单的说,SUN首先发展出SERVLET,其功能比较强劲,体系设计也很先进,只是,它输出HTML语句还是采用了老的CGI方式,是一句一句输出,所以,编写和修改HTML ...
- 如何解决GBK的编码的文件中的中文转换成为UTF-8编码的文件而且不乱码
首先我们必须明确一点,为什么正常转换会乱码? 因为我们的数据写入是GBK写入的,然后展示的话是按照文件保存形势展示的,前面保存形势是GBK,一致,所以不乱码,而后面将保存形势变成了UTF-8,但是写入 ...
- 暑假集训Chapter1 贪心
为什么要今天写呢? 明天全力研究Johnson和一些奇奇怪怪的贪心 今天把能写的都写了 T1T2太水了直接上代码吧 #include<bits/stdc++.h> #define LL l ...
- CodeForces 547E:Mike and Friends(AC自动机+DFS序+主席树)
What-The-Fatherland is a strange country! All phone numbers there are strings consisting of lowercas ...
- 【Lintcode】105.Copy List with Random Pointer
题目: A linked list is given such that each node contains an additional random pointer which could poi ...