以前发布过HanLP的Lucene插件,后来很多人跟我说其实Solr更流行(反正我是觉得既然Solr是Lucene的子项目,那么稍微改改配置就能支持Solr),于是就抽空做了个Solr插件出来,开源在Github上,欢迎改进。

HanLP中文分词solr插件支持Solr5.x,兼容Lucene5.x。

图1

快速上手

1、将hanlp-portable.jarhanlp-solr-plugin.jar共两个jar放入${webapp}/WEB-INF/lib下

2、修改solr core的配置文件${core}/conf/schema.xml:

<fieldType name="text_cn" class="solr.TextField">

<analyzer type="index">

<tokenizer class="com.hankcs.lucene.HanLPTokenizerFactory" enableIndexMode="true"/>

</analyzer>

<analyzer type="query">

<!-- 切记不要在query中开启index模式 -->

<tokenizer class="com.hankcs.lucene.HanLPTokenizerFactory" enableIndexMode="false"/>

</analyzer>

</fieldType>

<!-- 业务系统中需要分词的字段都需要指定type为text_cn -->

<field name="my_field1" type="text_cn" indexed="true" stored="true"/>

<field name="my_field2" type="text_cn" indexed="true" stored="true"/>

Solr5中文分词器详细配置

对于新手来说,上面的两步可能太简略了,不如看看下面的step by step。本教程使用Solr5.2.1,理论上兼容solr5.x。

放置jar

将上述两个jar放到solr-5.2.1/server/solr-webapp/webapp/WEB-INF/lib目录下。如果你想自定义词典等数据,将hanlp.properties放到solr-5.2.1/server/resources,该目录也是log4j.properties等配置文件的放置位置。HanLP文档一直在说“将配置文件放到resources目录下”,指的就是这个意思。作为Java程序员,这是基本常识。

启动solr

首先在solr-5.2.1\bin目录下启动solr:

1.solr start -f

用浏览器打开http://localhost:8983/solr/#/,看到如下页面说明一切正常:

图2

创建core

在solr-5.2.1\server\solr下新建一个目录,取个名字比如叫one,将示例配置文件solr-5.2.1\server\solr\configsets\sample_techproducts_configs\conf拷贝过来,接着修改schema.xml中的默认域type,搜索

1.   <fieldType name="text_general" class="solr.TextField" positionIncrementGap="100">

2.       ...

3.   </fieldType>

替换为

  1. <!-- 默认文本类型: 指定使用HanLP分词器,同时开启索引模式。
  2. 通过solr自带的停用词过滤器,使用"stopwords.txt"(默认空白)过滤。
  3. 在搜索的时候,还支持solr自带的同义词词典。-->
  4. <fieldType name="text_general" class="solr.TextField" positionIncrementGap="100">
  5. <analyzer type="index">
  6. <tokenizer class="com.hankcs.lucene.HanLPTokenizerFactory" enableIndexMode="true"/>
  7. <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
  8. <!-- 取消注释可以启用索引期间的同义词词典
  9. <filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
  10. -->
  11. <filter class="solr.LowerCaseFilterFactory"/>
  12. </analyzer>
  13. <analyzer type="query">
  14. <tokenizer class="com.hankcs.lucene.HanLPTokenizerFactory" enableIndexMode="true"/>
  15. <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
  16. <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
  17. <filter class="solr.LowerCaseFilterFactory"/>
  18. </analyzer>
  19. </fieldType>

意思是默认文本字段类型启用HanLP分词器,text_general还开启了solr默认的各种filter。

solr允许为不同的字段指定不同的分词器,由于绝大部分字段都是text_general类型的,可以说这种做法比较适合新手。如果你是solr老手的话,你可能会更喜欢单独为不同的字段指定不同的分词器及其他配置。如果你的业务系统中有其他字段,比如location,summary之类,也需要一一指定其type="text_general"。切记,否则这些字段仍旧是solr默认分词器,会造成这些字段“搜索不到”。

另外,切记不要在query中开启indexMode,否则会影响PhaseQuery。indexMode只需在index中开启一遍即可,要不然它怎么叫indexMode呢。

如果你不需要solr提供的停用词、同义词等filter,如下配置可能更适合你:

1. <fieldType name="text_cn" class="solr.TextField">

2.      <analyzer type="index">

3.          <tokenizer class="com.hankcs.lucene.HanLPTokenizerFactory" enableIndexMode="true"/>

4.      </analyzer>

5.      <analyzer type="query">

6.          <!-- 切记不要在query中开启index模式 -->

7.          <tokenizer class="com.hankcs.lucene.HanLPTokenizerFactory" enableIndexMode="false"/>

8.      </analyzer>

9.  </fieldType>

10.  <!-- 业务系统中需要分词的字段都需要指定type为text_cn -->

11.  <field name="my_field1" type="text_cn" indexed="true" stored="true"/>

12.  <field name="my_field2" type="text_cn" indexed="true" stored="true"/>

完成了之后在solr的管理界面导入这个core one:

图3

接着就能在下拉列表中看到这个core了:

图4

上传测试文档

修改好了,就可以拿一些测试文档来试试效果了。hanlp-solr-plugin代码库中的src/test/resources下有个测试文档集合documents.csv,其内容如下:

  1. id,title
  2. 1,你好世界
  3. 2,商品和服务
  4. 3,和服的价格是每镑15便士
  5. 4,服务大众
  6. 5,hanlp工作正常

代表着id从1到5共五个文档,接下来复制solr-5.2.1\example\exampledocs下的上传工具post.jar到resources目录,利用如下命令行将数据导入:

  1. java -Dc=one -Dtype=application/csv -jar post.jar *.csv

Windows用户的话直接双击该目录下的upload.cmd即可,Linux用户运行upload.sh。

正常情况下输出如下结果:

  1. SimplePostTool version 5.0.0
  2. Posting files to [base] url http://localhost:8983/solr/one/update using content-
  3. type application/csv...
  4. POSTing file documents.csv to [base]
  5. 1 files indexed.
  6. COMMITting Solr index changes to http://localhost:8983/solr/one/update...
  7. Time spent: 0:00:00.059
  8. 请按任意键继续. . .

同时刷新一下core one的Overview,的确看到了5篇文档:

图5

搜索文档

是时候看看HanLP分词的效果了,点击左侧面板的Query,输入“和服”试试:

图6

发现精确地查到了“和服的价格是每镑15便士”,而不是“商品和服务”这种错误文档:

图7

这说明HanLP工作良好。

要知道,不少中文分词器眉毛胡子一把抓地命中“商品和服务”这种错误文档,降低了查准率,拉低了用户体验,跟原始的MySQL LIKE有何区别?

索引模式的功能

索引模式可以对长词进行全切分,得到其中蕴含的所有词汇。比如“中医药大学附属医院”在HanLP索引分词模式下的切分结果为:

  1. 中0 医1 药2 大3 学4 附5 属6 医7 院8
  2. [0:3 1] 中医药/n
  3. [0:2 1] 中医/n
  4. [1:3 1] 医药/n
  5. [3:5 1] 大学/n
  6. [5:9 1] 附属医院/nt
  7. [5:7 1] 附属/vn
  8. [7:9 1] 医院/n

开启indexMode后,无论用户搜索“中医”“中医药”还是“医药”,都会搜索到“中医药大学附属医院”:

图8

高级配置

目前本插件支持如下基于schema.xml的配置:

图9

对于更高级的配置,HanLP分词器主要通过class path下的hanlp.properties进行配置,请阅读HanLP自然语言处理包文档以了解更多相关配置,如:

1.停用词

2.用户词典

3.词性标注

4.……

代码调用

在Query改写的时候,可以利用HanLPAnalyzer分词结果中的词性等属性,如

  1. String text = "中华人民共和国很辽阔";
  2. for (int i = 0; i < text.length(); ++i)
  3. {
  4. System.out.print(text.charAt(i) + "" + i + " ");
  5. }
  6. System.out.println();
  7. Analyzer analyzer = new HanLPAnalyzer();
  8. TokenStream tokenStream = analyzer.tokenStream("field", text);
  9. tokenStream.reset();
  10. while (tokenStream.incrementToken())
  11. {
  12. CharTermAttribute attribute = tokenStream.getAttribute(CharTermAttribute.class);
  13. // 偏移量
  14. OffsetAttribute offsetAtt = tokenStream.getAttribute(OffsetAttribute.class);
  15. // 距离
  16. PositionIncrementAttribute positionAttr = kenStream.getAttribute(PositionIncrementAttribute.class);
  17. // 词性
  18. TypeAttribute typeAttr = tokenStream.getAttribute(TypeAttribute.class);
  19. System.out.printf("[%d:%d %d] %s/%s\n", offsetAtt.startOffset(), offsetAtt.endOffset(), positionAttr.getPositionIncrement(), attribute, typeAttr.type());
  20. }

在另一些场景,支持以自定义的分词器(比如开启了命名实体识别的分词器、繁体中文分词器、CRF分词器等)构造HanLPTokenizer,比如:

  1. tokenizer = new HanLPTokenizer(HanLP.newSegment()
  2. .enableJapaneseNameRecognize(true)
  3. .enableIndexMode(true), null, false);
  4. tokenizer.setReader(new StringReader("林志玲亮相网友:确定不是波多野结衣?"));
  5. ...

反馈

技术问题请在Github上发issue ,大家一起讨论,也方便集中管理。博客留言、微博私信、邮件不受理任何HanLP相关的问题,谢谢合作!

反馈问题的时候请一定附上版本号、触发代码、输入输出,否则无法处理。

版权

Apache License Version 2.0

转载子码农场

全文检索Solr集成HanLP中文分词的更多相关文章

  1. 全文检索Solr集成HanLP中文分词【转】

    以前发布过HanLP的Lucene插件,后来很多人跟我说其实Solr更流行(反正我是觉得既然Solr是Lucene的子项目,那么稍微改改配置就能支持Solr),于是就抽空做了个Solr插件出来,开源在 ...

  2. Solr集成IK中文分词器

    1.将IKAnalyzer-2012-4x.jar拷贝到example\solr-webapp\webapp\WEB-INF\lib下: 2.在schema.xml文件中添加fieldType: &l ...

  3. 全文检索引擎Solr系列——整合中文分词组件mmseg4j

    默认Solr提供的分词组件对中文的支持是不友好的,比如:“VIM比作是编辑器之神”这个句子在索引的的时候,选择FieldType为”text_general”作为分词依据时,分词效果是: 它把每一个词 ...

  4. solr服务中集成IKAnalyzer中文分词器、集成dataimportHandler插件

    昨天已经在Tomcat容器中成功的部署了solr全文检索引擎系统的服务:今天来分享一下solr服务在海量数据的网站中是如何实现数据的检索. 在solr服务中集成IKAnalyzer中文分词器的步骤: ...

  5. Solr学习笔记之2、集成IK中文分词器

    Solr学习笔记之2.集成IK中文分词器 一.下载IK中文分词器 IK中文分词器 此文IK版本:IK Analyer 2012-FF hotfix 1 完整分发包 二.在Solr中集成IK中文分词器 ...

  6. 在Solr中配置中文分词IKAnalyzer

    李克华 云计算高级群: 292870151 交流:Hadoop.NoSQL.分布式.lucene.solr.nutch 在Solr中配置中文分词IKAnalyzer 1.在配置文件schema.xml ...

  7. Elasticsearch:hanlp 中文分词器

    HanLP 中文分词器是一个开源的分词器,是专为Elasticsearch而设计的.它是基于HanLP,并提供了HanLP中大部分的分词方式.它的源码位于: https://github.com/Ke ...

  8. 全文检索引擎Solr系列——整合中文分词组件IKAnalyzer

    IK Analyzer是一款结合了词典和文法分析算法的中文分词组件,基于字符串匹配,支持用户词典扩展定义,支持细粒度和智能切分,比如: 张三说的确实在理 智能分词的结果是: 张三 | 说的 | 确实 ...

  9. HanLP中文分词Lucene插件

    基于HanLP,支持包括Solr(7.x)在内的任何基于Lucene(7.x)的系统. Maven <dependency> <groupId>com.hankcs.nlp&l ...

随机推荐

  1. http 协议三次握手

    HTTP是超文本传输协议,信息是明文传输.TPC/IP协议是传输层协议,主要解决数据如何在网络中传输.HTTP是应用层协议,主要解决如何包装数据. [HTTP与TCP/IP]和其他的协议在最初OSI模 ...

  2. Java学习笔记8(面向对象3:接口)

    接口的概念: 接口是功能的集合,同样可以看最做事一种数据类型,是比抽象类更为抽象的"类”. 接口之描述所应该具备的方法,并没有具体实现,具体的实现有接口的实现类(相当于接口的子类)来完成.这 ...

  3. Linux并发执行很简单,这么干就对了

    嗯,就像标题说的那么简单而已 &的并发功能 time for i in `grep server /etc/hosts | awk '{print $1}'`; do (ssh $i &quo ...

  4. Hibernate乐观锁无法Catch到org.hibernate.StaleObjectStateException

    Hibernate乐观锁无法Catch到org.hibernate.StaleObjectStateException时,请Catch HibernateOptimisticLockingFailur ...

  5. 【Python】xml 解析

    1. XML:指可扩展标记语言,是一种标记语言,用于存储数据和传输数据,但没有像HTML那样具有预定义标签,需要程序猿自定义标签 2. XML的解析:读取XML数据结构中的某些信息,比如读取书的属性 ...

  6. 网络协议理论,http协议,数据结构,常用返回码

    一.网络协议理论 先是DNS协议 将域名转化成IP地址 这个你要知道 域名只是人记着方便 计算机记的是IP 然后是TCPIP协议 数据在传输过程中可能要经过陆游器 涉及到的是ARP协议 将IP地址转换 ...

  7. Spring Boot 揭秘与实战 源码分析 - 工作原理剖析

    文章目录 1. EnableAutoConfiguration 帮助我们做了什么 2. 配置参数类 – FreeMarkerProperties 3. 自动配置类 – FreeMarkerAutoCo ...

  8. 大数据-02-Scala入门

    Scala 简介 它是一门基于JVM的面向函数和面向对象的编程语言, 它包含了求值表达式,闭包,切片操作,模式匹配,隐式转换等特性. 可变量/不可变量 可变集合/不可变集合.集合操作 函数 值函数 求 ...

  9. 一个跳转提示页面---JS

    //一个跳转提示页面   <script type="text/javascript">   var s=5;     function go(){        do ...

  10. cell-augmented

    https://zhuanlan.zhihu.com/p/33147353 https://blog.csdn.net/thm225679/article/details/79689008 https ...