关于Solr搜索标点与符号的中文分词你必须知道的(mmseg源码改造)

摘要:在中文搜索中的标点、符号往往也是有语义的,比如我们要搜索“C++”或是“C#”,我们不希望搜索出来的全是“C”吧?那样对程序员来说是个噩梦。然而在中文分词工具mmseg中,它的中文分词是将标点与符号均去除的,它认为对于中文来讲标点符号无意义,这明显不能满足我们的需求。那么怎样改造它让它符合我们的要求呢?本文就是针对这一问题的详细解决办法,我们改mmseg的源代码。

关键字:Solr, mmseg, 中文, 分词, 标点, 符号, 语义

前提:Solr(5.0.0版本),mmseg4j(1.10.0版本)

作者:王安琪(博客地址:http://www.cnblogs.com/wgp13x/

0、Solr的mmseg默认中文分词效果

做个实验,入Solr的语句为:t#\"\&\*CTY  C# "#"&*^#とう華뭄내ㅛ  #\"\&\*C8:8。3  C# \"#\"&*^#√とう ,使用的是mmseg中的“max-word”型分词。分词后会变成什么样呢?在对Solr进行简单的mmseg配置操作后,我们在Solr的Analysis中对以上语句进行分析,如下图所示。

图0-1 mmseg默认中文分词效果

从上图中可以看出,默认的mmseg“max-word”型分词将所有的标点、符号都抛弃掉了,余下的只是中文、数字、英文、韩文、日文等。经过mmseg的其他类型如:“complex”和“simple”分析操作后,其结果也是把所有的标点、符号均删除。然而使用Ansj进行中文分词的话,其默认是不删除标点符号的。使用IKAanalyzer来进行中文分词,它也删除掉所有的标点符号。具体情况见博客:中文分词器性能比较 http://www.cnblogs.com/wgp13x/p/3748764.html

mmseg在中文分词过程中删除标点符号,这直接导致搜索不出标点和符号,因为被删除的将不被建立索引,如:搜索“#”,返回的是所有。为了解释这个问题,我们分析一下Solr创建索引的过程。

1、Solr创建索引的过程

在创建索引的过程中,进入的每一句字符串,均依据fieldType中配置的:tokenizer及以下的filter,从上至下依次处理。正如下图所示的,当进入的字符串为 #Yummm :) Drinking a latte at ... 第一步经过StandardTokenizer后,变成了一个个单词:Yummm | Drinking | a | latte | at | ,可以看出这一步就已经将标点符号去除掉了,并使用标点符号和空格将句子划分成一个个单词。第二步经过的是StopFilter,它将stop words:a at in 等删掉,它认为他们是无语义的词汇,这要看具体情况了,这步结束后原文变成了:Yummm | Drinking | latte | 。第三步是经过LowercaseFilter,很明显从字面上解释就是把所有的单词小写化,最终的结果是:yummm | drinking | latte |。

 图1-1 Solr创建索引的过程

在搜索的过程中,新入的搜索字符串,也需要经历这几个过程,再将经历这些过程后的单词以“与”或“或”的关系,进行搜索。这就解释了,上一个问题,为什么输入的搜索条件是“#”,返回的是所有,因为条件经历这些过程后,条件是空,即搜索所有了。

2、Solr的mmseg经过改进后的中文分词效果

经过我们的改进,在入Solr的语句为:!,工;1 - 低 ... 时, 中文分词效果如下图所示。

图2-1 mmseg经过改进后的中文分词效果

从上图可以看到,经过MMST后,所有的单词都已经大写小化了,所以可以去除LowerCaseFilter,对结果不影响,即在配置中将<filter class="solr.LowerCaseFilterFactory"/>去掉。再次分析的效果如下图所示:

图2-2 mmseg经过改进后并去除LowerCaseFilter后的中文分词效果

可以看出,C++这样输入的输出变成了:c | + | +,这样的话,当搜索条件为入C++时,便可以匹配出来了!这正是我们想要的。最终效果可以从下图中看出,在图2-3中将一串带有标点符号的字符串添加入Solr的mmseg fild中。在图2-4中对mmseg fild搜索带有标点符号的字符串,可以看到,刚添加的字符串被正确搜索到了!

          图2-3 添加带有标点符号的Document

图2-4 搜索条件带有标点符号的搜索结果

3、Solr的mmseg的中文分词效果改进办法

首先,根据mmseg作者chenlb  https://github.com/chenlb/mmseg4j-solr 的提示与启发,可以在next()函数中进行修改源码,以达到不去除标点符号的目的。我们在mmseg源码中找到MMSeg类中存在next()函数,通过阅读源码,我们知道,这即是对已识别的各种类型的字符进行分门别类地处理,如数字、字母、韩语等。函数内对其他的字符均视为无效字符,其中标点与符号便落入了此类别,其对此类别的字符处理办法是:“不理睬”。下面就是我依照中文字符的处理过程,编写了标点与符号的处理过程,同时对空格及Tab、\n这些字符采取“不理睬”策略,因为他们真的是无语义的,具体的代码如下。

  1. public Word next() throws IOException {
  2. // 先从缓存中取
  3. Word word = bufWord.poll();
  4. ;
  5. if (word == null) {
  6. bufSentence.setLength(0);
  7. int data = -1;
  8. boolean read = true;
  9. while (read && (data = readNext()) != -1) {
  10. read = false; // 默认一次可以读出同一类字符,就可以分词内容
  11. int type = Character.getType(data);
  12. String wordType = Word.TYPE_WORD;
  13. switch (type) {
  14. 。。。。。。。。
  15. case Character.SPACE_SEPARATOR:
  16. case Character.CONTROL:
  17. read = true;
  18. break;
  19. default:
  20. // 其它认为无效字符
  21. // read = true;
  22. bufSentence.appendCodePoint(data);
  23. readChars(bufSentence, new ReadCharByType(type));
  24. // bufWord.add(createWord(bufSentence, Word.TYPE_LETTER));
  25. currentSentence = createSentence(bufSentence);
  26. bufSentence.setLength(0);
  27. }// switch
  28. // 中文分词
  29. if (currentSentence != null) {
  30. do {
  31. Chunk chunk = seg.seg(currentSentence);
  32. for (int i = 0; i < chunk.getCount(); i++) {
  33. bufWord.add(chunk.getWords()[i]);
  34. }
  35. } while (!currentSentence.isFinish());
  36. currentSentence = null;
  37. }
  38. word = bufWord.poll();
  39. }
  40. return word;
  41. }

经过编译后,将MMSeg类相关的class替换到mmseg4j-core-1.10.0.jar目录下,如图3-1所示。然后重新部署Solr,一切运行正常!

图3-1 编译并替换MMSeg

4、Solr的配置补充

经过刚才的操作,已经解决了标点与符号删除的问题。下面讲一下autoGeneratePhraseQueries的配置。

图4-1 mmSeg配置

如上图的配置所示,autoGeneratePhraseQueries="false",autoGeneratePhraseQueries配置为false有下面的作用:将搜索关键词分词后,以或的条件进行搜索,比如入的是 ,搜索关键词是,关键词经过分词后有些分词结果不在Doc范围内,但是仍旧可以搜索出来;然而如果autoGeneratePhraseQueries="true" ,则搜索不出来,此时是且的关系。

这简直是太棒了!

关于Solr搜索标点与符号的中文分词你必须知道的(mmseg源码改造)的更多相关文章

  1. Lucene全文搜索之分词器:使用IK Analyzer中文分词器(修改IK Analyzer源码使其支持lucene5.5.x)

    注意:基于lucene5.5.x版本 一.简单介绍下IK Analyzer IK Analyzer是linliangyi2007的作品,再此表示感谢,他的博客地址:http://linliangyi2 ...

  2. 【Lucene3.6.2入门系列】第14节_SolrJ操作索引和搜索文档以及整合中文分词

    package com.jadyer.solrj; import java.util.ArrayList; import java.util.List; import org.apache.solr. ...

  3. Solr入门之(8)中文分词器配置

    Solr中虽然提供了一个中文分词器,但是效果很差,可以使用IKAnalyzer或Mmseg4j 或其他中文分词器. 一.IKAnalyzer分词器配置: 1.下载IKAnalyzer(IKAnalyz ...

  4. 我的搜索优化记录(一):中文分词优化IK Analyzer

    搜索绝对不仅仅是搭起框架,跑出结果就完成的工作,之后分词.排序等等的优化才是重头戏. 先交代下背景:这个搜索是我一个人负责搭建并优化的项目,主要索引对象为歌曲.歌手MV等等. 使用技术:Lucene. ...

  5. 【中文分词】简单高效的MMSeg

    最近碰到一个分词匹配需求--给定一个关键词表,作为自定义分词词典,用户query文本分词后,是否有词落入这个自定义词典中?现有的大多数Java系的分词方案基本都支持添加自定义词典,但是却不支持HDFS ...

  6. Spring实战(中文4,5版) PDF含源码

    Spring实战 读者评价 看了一半后在做评论,物流速度挺快,正版行货,只是运输过程有点印记,但是想必大家和你关注内容,spring 4必之3更加关注的是使用注解做开发,对于初学者还是很有用,但是不排 ...

  7. solr 7+tomcat 8 + mysql实现solr 7基本使用(安装、集成中文分词器、定时同步数据库数据以及项目集成)

    基本说明 Solr是一个开源项目,基于Lucene的搜索服务器,一般用于高级的搜索功能: solr还支持各种插件(如中文分词器等),便于做多样化功能的集成: 提供页面操作,查看日志和配置信息,功能全面 ...

  8. Solr4.0+IKAnalyzer中文分词安装(转)

    有近2年没接触Solr跟Lucene了,这2年自己跟solr/lucene都发生了很多变化.不过有种疏途同归的感觉,那就是都向分布式/云和监控靠了.2年前接触了solrcloud,那时大概玩了一周.那 ...

  9. Solr4.0+IKAnalyzer中文分词安装

    1.依赖: JDK1.6,Tomcat 5.5,Solr 4.0.0,IKAnalyzer 2012FF Tomcat虽然不是必须,但觉得上生产环境的话,还是得用Tomcat,便于统一管理和监控. T ...

随机推荐

  1. IntelliTrace简介

    解决无法复现bug所使用的策略是在遇到bug时捕获尽可能多的信息,在使用IntelliTrace进行调试时可以充分利用这些信息.最令人称道的一个功能在于bug本身可以自动修复. 打开IntelliTr ...

  2. Node.js爬虫数据抓取乱码问题总结

    一.非UTF-8页面处理 1.背景 windows-1251编码 比如俄语网站:https://vk.com/cciinniikk 可耻地发现是这种编码 所有这里主要说的是 Windows-1251( ...

  3. Unity中简单使用Opengl

    简介 由于项目特殊需求,需要在unity中使用一些OpenGL的东西来绘制图形(PS:其实就是有一个拖尾算法只有OpenGL版本~~~懒得改了,直接在unity中使用OpenGL算了).所以琢磨咯下如 ...

  4. Azure开发者任务之四:在Azure SDK 1.3中挂载调试器的错误

    我安装了Windows Azure SDK的1.3版本.我试着创建了一个Azure的“Hello World”应用程序. 我按了“F5”,然后我得到了下面这个错误: 我尝试了“Ctrl+F5”:不使用 ...

  5. easyui-简单用法寄一些属性

    Easyui 总结 优点: A.简单易用 继承 jQuery 简易使用特性,提供高度抽象接口,短期改善网站易用性. B.开源免费 采用 MIT & GPL 双协议授权,轻松满足自由产品至企业产 ...

  6. Studio for Winforms FlexGrid:导出到 PDF 文件

    本篇文章主要介绍如何导出 FlexGrid 到 PDF 格式文件.本文源于论坛用户,有多个用户提出如何把 FlexGrid 导出到 PDF 文件的需求.在这里共享给大家. 当前,ComponentOn ...

  7. 泛函编程(14)-try to map them all

    虽然明白泛函编程风格中最重要的就是对一个管子里的元素进行操作.这个管子就是这么一个东西:F[A],我们说F是一个针对元素A的高阶类型,其实F就是一个装载A类型元素的管子,A类型是相对低阶,或者说是基础 ...

  8. .NET AES加解密(128位)

    AES加密(128位): /// <summary> /// 有密码的AES加密 /// </summary> internal static string Encrypt(s ...

  9. mysql innodb表 utf8 gbk占用空间相同,毁三观

    昨天因为发生字符集转换相关错误,今天想验证下utf8和gbk中英文下各自空间的差距.这一测试,绝对毁三观,无论中文还是中文+英文,gbk和utf8占用的实际物理大小完全相同,根本不是理论上所述的“UT ...

  10. 「C语言」单链表/双向链表的建立/遍历/插入/删除

    最近临近期末的C语言课程设计比平时练习作业一下难了不止一个档次,第一次接触到了C语言的框架开发,了解了View(界面层).Service(业务逻辑层).Persistence(持久化层)的分离和耦合, ...