Solr的中英文分词实现

对于Solr应该不需要过多介绍了,强大的功能也是都体验过了,但是solr一个较大的问题就是分词问题,特别是中英文的混合分词,处理起来非常棘手。 虽然solr自带了支持中文分词的cjk,但是其效果实在不好,所以solr要解决的一个问题就是中文分词问题,这里推荐的方案是利用ik进行分词。

ik是较早作中文分词的工具,其效果也是得到多数用户认同。但是现在作者似乎更新缓慢,对于最新的solr4.4支持不好,最新的更新也停留在2012年。

虽然不支持4.4版本(这也不是作者的错,solr的lucene的新版本接口都进行了修改,除非修改实现不然就没法向下兼容),但是我们也有办法的,我们可以利用他的分词工具自己封装一个TokenizerFactory,通过实现最新的4.4接口就可以让solr4.4用上ik了。

首先就是就在下载ik的原码,最新版是 然后自己实现一个TokenizerFactory:

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

<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。

<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不就可以了,而且这一点也不复杂,这里就不细说了,有机会再专门写一个。

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

<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服务于你的项目。

参考:

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

转载于:https://my.oschina.net/zyc1016/blog/176219

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Solr 9.2.0默认使用Lucene 8.6.0,其自带了一个中文分词器SmartChineseAnalyzer。 在Solr中配置中文分词器的步骤如下: 1. 在solrconfig.xml中配置分词器 在schema.xml中定义field时,需要指定使用分词器,例如: ``` <field name="text" type="text_cn" indexed="true" stored="true"/> ``` 在solrconfig.xml中,需要配置text_cn类型的分词器,例如: ``` <fieldType name="text_cn" class="solr.TextField"> <analyzer type="index"> <tokenizer class="org.apache.lucene.analysis.cn.smart.SmartChineseTokenizerFactory"/> </analyzer> <analyzer type="query"> <tokenizer class="org.apache.lucene.analysis.cn.smart.SmartChineseTokenizerFactory"/> </analyzer> </fieldType> ``` 其中,tokenizer指定了使用分词器,这里使用的是SmartChineseTokenizerFactory,它是SmartChineseAnalyzer的底层分词器。 2. 配置停用词 在solrconfig.xml中,可以配置停用词,在分词时将停用词过滤掉,例如: ``` <filter class="solr.StopFilterFactory" words="stopwords.txt" ignoreCase="true" /> ``` 其中,words指定了停用词文件的路径,可以自己定义。 3. 配置同义词 在solrconfig.xml中,可以配置同义词,在分词时将同义词替换掉,例如: ``` <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true" /> ``` 其中,synonyms指定了同义词文件的路径,可以自己定义。expand指定是否将同义词扩展,例如"中国, 中国人, 中国人民",如果expand=true,则搜索"中国"时会将其扩展为"中国 中国人 中国人民"。 以上就是在Solr 9.2.0中配置中文分词器的基本步骤。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值