设为首页 收藏本站
查看: 823|回复: 0

[经验分享] Solr的中英文分词实现(转载)

[复制链接]

尚未签到

发表于 2016-12-16 06:32:30 | 显示全部楼层 |阅读模式
对于Solr应该不需要过多介绍了,强大的功能也是都体验过了,但是solr一个较大的问题就是分词问题,特别是中英文的混合分词,处理起来非常棘手。 虽然solr自带了支持中文分词的cjk,但是其效果实在不好,所以solr要解决的一个问题就是中文分词问题,这里推荐的方案是利用ik进行分词。
ik是较早作中文分词的工具,其效果也是得到多数用户认同。但是现在作者似乎更新缓慢,对于最新的solr4.4支持不好,最新的更新也停留在2012年。
虽然不支持4.4版本(这也不是作者的错,solr的lucene的新版本接口都进行了修改,除非修改实现不然就没法向下兼容),但是我们也有办法的,我们可以利用他的分词工具自己封装一个TokenizerFactory,通过实现最新的4.4接口就可以让solr4.4用上ik了。
首先就是就在下载ik的原码,最新版是 然后自己实现一个TokenizerFactory:
 

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35


package org.wltea.analyzer.lucene;


 

import java.io.Reader;


import java.util.Map;


 

import org.apache.lucene.analysis.Tokenizer;


import org.apache.lucene.analysis.util.TokenizerFactory;


import org.apache.lucene.util.AttributeSource.AttributeFactory;


 

public class IKAnalyzerTokenizerFactory extends TokenizerFactory{


 

    private boolean useSmart;


 

    public boolean useSmart() {


        return useSmart;


    }


 

    public void setUseSmart(boolean useSmart) {


        this.useSmart = useSmart;


    }


 

    public IKAnalyzerTokenizerFactory(Map<String, String> args) {


        super(args);


        assureMatchVersion();


        this.setUseSmart(args.get("useSmart").toString().equals("true"));


    }


 

 

    @Override


    public Tokenizer create(AttributeFactory factory, Reader input) {


        Tokenizer _IKTokenizer = new IKTokenizer(input , this.useSmart);


        return _IKTokenizer;


    }


 

}








 
然后重新打包jar放到solr的执行lib里,同时新建一个fieldType
 

?


1

2

3

4

5

6

7

8


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


  <analyzer type="index">


    <tokenizer class="org.wltea.analyzer.lucene.IKAnalyzerTokenizerFactory" useSmart="false"/>


  </analyzer>


  <analyzer type="query">


    <tokenizer class="org.wltea.analyzer.lucene.IKAnalyzerTokenizerFactory" useSmart="true"/>


  </analyzer>


</fieldType>









 
测试一下我们新的分词器:

// 输入
移动互联网
// 输出
移动,互联网,互联,联网


从结果来看,其效果还是比较不错的。
搞定了中文我们需要搞定英文 英文简单的分词是按照空格,标点,stopword等来分词。 比如I'm coding一般可以分词为I'm, coding或者I, m, coding。一般情况下这样也是可以接受的,但是如果用户输入code,是否应该搜到结果呢,如果要搜到该结果,那么我们需要处理我们的英文分词。
这里提供一种简单的实现,就是采用NGramFilterFactory,该过滤器简单的按照长度对词进行切分,该过滤器有两个参数minGramSize和maxGramSize,分别表示最小和最大的切分长度,默认是1和2。
 

?


1

2

3

4


<analyzer>


  <tokenizer class="solr.StandardTokenizerFactory"/>


  <filter class="solr.NGramFilterFactory" minGramSize="1" maxGramSize="4"/>


</analyzer>









 
比如设置(min,max)为(3,5),我们上面的句子“I'm coding”会得到以下的结果:

I'm,cod,codi,codin,coding,odi,odin,oding,din,ding,ing


当然这里也会有问题,就是小于3个词长的都会被过滤调,特别是中文和英文采用的是同一词长处理,如果min设为3,那么像我,我们这样的都会被过滤,解决办法就是min设为1,这样的结果就是会大大增加索引记录。影响检索速度。好处就是可以实现字母级别的匹配,然后通过设置匹配度阔值提升了搜索质量。
分别处理完了中文和英文,那么就要混合中英文处理了



  • 方案一是使用StandardTokenizerFactory和NGramFilterFactory,加上辅助的StopFilterFactory和LowerCaseFilterFactory等过滤器处理。也就是中文默认是按字逐个分开,当然前提是NGramFilterFactory的minGramSize要设置为1。


  • 方案二则是IKAnalyzerTokenizerFactory和NGramFilterFactory,通过ik实现对词的索引,然后在通过ngram进行长度分割。即在方案一的基础上增加对词的索引,提升索引质量。


  • 方案一和方案二如果还不够和谐的,那么我们还有个办法就是自定义的反感三,所谓自定义,自己写个tokenizer或者filter不就可以了,而且这一点也不复杂,这里就不细说了,有机会再专门写一个。


最后来个整合的配置参考一下:
 

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15


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


  <analyzer type="index">


    <tokenizer class="org.wltea.analyzer.lucene.IKAnalyzerTokenizerFactory"  useSmart="false"/>


    <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />


    <filter class="solr.LowerCaseFilterFactory"/>


    <filter class="solr.NGramFilterFactory" minGramSize="1" maxGramSize="20"/>


  </analyzer>


  <analyzer type="query">


    <tokenizer class="org.wltea.analyzer.lucene.IKAnalyzerTokenizerFactory"  useSmart="true"/>


    <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />


    <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>


    <filter class="solr.LowerCaseFilterFactory"/>


    <filter class="solr.NGramFilterFactory" minGramSize="1" maxGramSize="10"/>


  </analyzer>


</fieldType>









 
这里所提出的并不是最优的方案,或者说可能是比较傻瓜化的方案,但是solr的优势就是自由,你可以自己组合各种tokenizer和filter来实现你要的效果,或者干脆自己去实现tokenizer和filter,然后让强大的solr服务于你的项目。
参考:


  • https://cwiki.apache.org/confluence/display/solr/About+This+Guide


  • https://code.google.com/p/ik-analyzer/

原文链接:http://thinkjet.me/solr-lucene-tokenizer-filter.html

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-314781-1-1.html 上篇帖子: solr搜索服务器配置mmseg4j分词 下篇帖子: solr之functionQuery(函数查询)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表