一、简介
分析器是solr中一个很重要的组件,在建立索引、搜索出想要的结果时,发挥了非常大的作用,这是solr已经定义好的一段包含分析器的fieldType示例
<fieldType name="text_en" class="solr.TextField" positionIncrementGap="100"> <analyzer type="index"> <tokenizer class="solr.StandardTokenizerFactory"/> <filter class="solr.StopFilterFactory" words="lang/stopwords_en.txt" ignoreCase="true"/> <filter class="solr.LowerCaseFilterFactory"/> <filter class="solr.EnglishPossessiveFilterFactory"/> <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/> <filter class="solr.PorterStemFilterFactory"/> </analyzer> <analyzer type="query"> <tokenizer class="solr.StandardTokenizerFactory"/> <filter class="solr.SynonymFilterFactory" expand="true" ignoreCase="true" synonyms="synonyms.txt"/> <filter class="solr.StopFilterFactory" words="lang/stopwords_en.txt" ignoreCase="true"/> <filter class="solr.LowerCaseFilterFactory"/> <filter class="solr.EnglishPossessiveFilterFactory"/> <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/> <filter class="solr.PorterStemFilterFactory"/> </analyzer> </fieldType>
1.分析器(Analyzer)
告诉Solr在建立索引和搜索的时候,如何处理文档内容,类型(type)一般为index或query
2.分词器(Tokenizer):
如何将一段完整的内容拆分成单独的词或词组,solr中定义了很多带分析器的文本类型,但中文的需要自己定义,目前有很多优秀的中文分词器(mmseg4j、IK等)
3.过滤器(Filter)
进过Tokenizer处理后,后续处理的组件,比如全转成小写等
4. Why?
为什么要用分词,以查询一段文字“詹姆斯:NBA巨星,首轮状元秀,绰号小皇帝。”(对应的field未定义任何的分词器),我们如果查询“状元秀”,是查不到这条记录的,当然你说可以加通配符,但是如果我们还要做高亮显示查询的这个词呢?
这时如果我们将对应字段的类型加上index分词器,在建立索引时就会对内容进行合适的拆分,查询时也会对查询字符串进行分词拆分,这样即使我们查询“小皇帝状元秀”也可以获得我们想要的结果
二、分析器的配置(中文分词mmseg4j的配置)
这里我solr的版本是6.5.0,mmseg4j的版本是2.4.0
1. 常用中文分词介绍
paoding:支持不限制个数的用户自定义词库,纯文本格式,一行一词,使用后台线程检测词库的更新,自动编译更新过的词库到二进制版本,并加载
mmseg4j:自带sogou词库,支持名为 wordsxxx.dic, utf8文本格式的用户自定义词库,一行一词。不支持自动检测。 -Dmmseg.dic.path
IK:支持api级的用户词库加载,和配置级的词库文件指定,无 BOM 的 UTF-8 编码,/r/n 分割。不支持自动检测。
2.mmseg4j分词器配置
将下载好的mmseg4j包导入到solr的WEB-INF/lib下,并在schema配置文件中添加以下内容:
<fieldType name="text_mmseg4j_Complex" class="solr.TextField"> <analyzer> <tokenizer class="com.chenlb.mmseg4j.solr.MMSegTokenizerFactory" mode="complex" dicPath="dic"/> </analyzer> </fieldType>
将之前定义的core_test中short_desc字段定义为text_mmseg4j_Complex类型,重建索引后,我们查询"状元秀小皇帝",只返回了一条记录
{ "responseHeader" : { "status" : 0, "QTime" : 2, "params" : { "q" : "short_desc:状元秀小皇帝", "indent" : "on", "wt" : "json", "_" : "1493135606415" } }, "response" : { "numFound" : 1, "start" : 0, "docs" : [{ "name" : "LeBron James", "id" : "12b3e4b030314f55a89006769b8b743a", "short_desc" : "NBA巨星,首轮状元秀,克里夫兰骑士队当家球星,3届总冠军得主,场上司职小前锋,绰号“小皇帝”", "age" : 32, "tags" : ["小皇帝", "吾皇"], "_version_" : 1565666158942617600 }] } }
用提供的分析器页面也可以看到分词的结果比原来用标准分词器(完全拆成了一个个的汉字,而忽了语义)更符合自然意义
//mmseg4j基于正向最大匹配,分词结果 MMST 状元 秀 小 皇帝
3.mmseg4j的三种模式区别
mmseg4j涉及到了Simple、Complex、max-word三种分词方法,前两个都是基于正向最大匹配,第三种是在Complex算法基础上实现的最多分词方法。
1)正向最大匹配:就是将一段字符串进行分隔,其中分隔 的长度有限制,然后将分隔的子字符串与字典中的词进行匹配,如果匹配成功则进行下一轮匹配,直到所有字符串处理完毕,否则将子字符串从末尾去除一个字,再进行匹配,如此反复。
2)三种模式分词实例
原字符串:阿根廷足球巨星
Simple、Complex分词结果:阿根廷 足球巨星
Max-Word分词结果:阿 根 廷 足球 巨星
三.自定义词库
可能注意到前面tokenizer配置了dicPath属性(dic),这里是指定自定义词库的目录,可以是绝对路径也可以是现对路径,相对路径为"{solr.home}/core_name/词库目录",词库文件words开头并以".dic"结尾,如words-myown.dic。
注意,如果你的词库文件也是words.dic会覆盖对应solr-core.jar包中预定义的词库文件。
1.动态加载词库
通过一个简单的配置就可以让mmseg4j动态加载词库
首先在solrconfig.xml中配置一个requestHandler,其中dicPath和fieldType配置的dicPath属性值相同
<requestHandler name="/mmseg4j" class="com.chenlb.mmseg4j.solr.MMseg4jHandler" > <lst name="defaults"> <str name="dicPath">dic</str> </lst> </requestHandler>
然后我们就可以通过URL(http://localhost:10001/solr/core_test/mmseg4j?reload=true)来通知其重新加载词库