文档章节

IKAnalyzer -- lucene6.6适配

柳初心
 柳初心
发布于 2017/07/21 17:35
字数 1055
阅读 232
收藏 1

前言

在中文分词器中, IKAnalyzer 做的是相对不错的,有着细度分割和智能使用两个模式 。
但是,这个版本因为太陈旧,作者不再维护,(项目估计是。。。),所以与现在的Lucene 6.6 版本差距有些大。所以,我就根据网上各位大神的文章,加上自己对 API 与源码的阅读,稍微的进行了改动,可以简单的运行。
注: 这里的简单是指,可以简单的运行源码 中的简单案例。

正文

项目介绍

  1. IKAnaylzer版本: IK Analyzer 2012FF 感谢提供的分词源码 http://git.oschina.net/wltea/IK-Analyzer-2012FF
  2. lucene 版本:lucene 6.60

代码改动

###1.对IKTokenizer的改动 源码

  /**
   * Lucene 4.0 Tokenizer适配器类构造函数
   * @param in
   * @param useSmart
   */
  public IKTokenizer(Reader in, boolean useSmart) {
    super(in);
    offsetAtt = addAttribute(OffsetAttribute.class);
    termAtt = addAttribute(CharTermAttribute.class);
    typeAtt = addAttribute(TypeAttribute.class);
    _IKImplement = new IKSegmenter(input, useSmart);
  }

经查阅 lucene 源码
Tokenizer类的构造器已经不再接收 Reader 源码如下

    protected Tokenizer() {
        this.input = ILLEGAL_STATE_READER;
        this.inputPending = ILLEGAL_STATE_READER;
    }

    protected Tokenizer(AttributeFactory factory) {
        super(factory);
        this.input = ILLEGAL_STATE_READER;
        this.inputPending = ILLEGAL_STATE_READER;
    }

因此改动 IKTokenizer 类 ,如下

    public IKTokenizer( boolean useSmart) {
        super();
        offsetAtt = addAttribute(OffsetAttribute.class);
        termAtt = addAttribute(CharTermAttribute.class);
        typeAtt = addAttribute(TypeAttribute.class);
        //传入 IKSegmenter 的 input Reader  流,会被 父类 Tokenizer 类的无参构造器
        //初始化为 this.input = ILLEGAL_STATE_READER;
        _IKImplement = new IKSegmenter(input, useSmart);
    }

去除了 Reader 形参 。 默认调用 父类 的 无参构造函数 Tokenizer()
注:在该博客下发现,还需要配置分词器工厂类,因此还要多增加一段构造器代码,如下

    //方便创建 工厂类
    public IKTokenizer(AttributeFactory factory, boolean useSmart) {
        super(factory);
        offsetAtt = addAttribute(OffsetAttribute.class);
        termAtt = addAttribute(CharTermAttribute.class);
        typeAtt = addAttribute(TypeAttribute.class);
        _IKImplement = new IKSegmenter(input, useSmart);
    }

###2. 对**IKAnalyzer ** 的改动 源码

  /**
   * 重载Analyzer接口,构造分词组件
   */
  @Override
  protected TokenStreamComponents createComponents(String fieldName, final Reader in) {
    Tokenizer _IKTokenizer = new IKTokenizer(in, this.useSmart());
    return new TokenStreamComponents(_IKTokenizer);
  }

lucene 6.6 关于 Analyzer 接口中 关于 createComponents() 方法的源码

protected abstract Analyzer.TokenStreamComponents createComponents(String var1);

结合上文中对 IKTokenizer 源码的改动,因此需要去除 参数 Reader in
改动的代码 如下:

	/**
	 * 重载Analyzer接口,构造分词组件
	 */
	@Override
	protected TokenStreamComponents createComponents(String fieldName) {
		Tokenizer _IKTokenizer = new IKTokenizer(this.useSmart());
		return new Analyzer.TokenStreamComponents(_IKTokenizer);
	}

3. 对SWMCQueryBuilder 的改动

源码如下:

    // 借助lucene queryparser 生成SWMC Query
    QueryParser qp = new QueryParser(Version.LUCENE_43, fieldName, new StandardAnalyzer(
        Version.LUCENE_43));
    qp.setDefaultOperator(QueryParser.AND_OPERATOR);
    qp.setAutoGeneratePhraseQueries(true);

由于新版本的 lucene 已经不在使用 Version 类 进行定义,(我的上一篇lucene6.6 学习心得说的很清楚)因此需要将之移除。
移除后,改动版本如下:

		//借助lucene queryparser 生成SWMC Query
		QueryParser qp = new QueryParser(fieldName, new StandardAnalyzer());
		qp.setDefaultOperator(QueryParser.AND_OPERATOR);
		qp.setAutoGeneratePhraseQueries(true);

###4. 对**IKQueryExpressionParser ** 的改动 IKQueryExpressionParser 类中方法 BooleanQuery ,在近期的 lucene 中有了较大改动,不知道的话,可以 查阅我的上一篇文章lucene6.6 学习心得. 因此源码中对 IKQueryExpressionParser 类中关于 BooleanQuery 的方法都需要进行更改。
因为方法中代码过多 , 因此,我选取其中比较关键的几个地方,进行展示。
关键源码如下:

private Query toBooleanQuery(Element op) {
BooleanQuery resultQuery = new BooleanQuery();
Query q2 = this.querys.pop();
Query q1 = this.querys.pop();
BooleanClause[] clauses = ((BooleanQuery) q1).getClauses();
resultQuery.add(c);
return resultQuery;
}

改动代码如下:
1.数组版本

private Query toBooleanQuery(Element op){
BooleanQuery.Builder builder = new BooleanQuery.Builder();
Query q2 = this.querys.pop();    
Query q1 = this.querys.pop();

 //因为,我看源码,并没有发现会增删的地方 ,于是直接转成了数组 
//迭代器版本的在下文
if(q1 instanceof BooleanQuery){    
    BooleanClause[] clauses =(BooleanClause[]) ((BooleanQuery)q1).clauses().toArray();
 if(clauses.length > 0
    && clauses[0].getOccur() == Occur.MUST){
    for(BooleanClause c : clauses){
        builder.add(c);
    }
    }else{
    builder.add(q1,Occur.MUST);
    }

     return builder.build();
}

2.迭代器版本

private Query toBooleanQuery(Element op){
BooleanQuery.Builder builder = new BooleanQuery.Builder();

Query q2 = this.querys.pop();    
Query q1 = this.querys.pop();

if(q1 instanceof BooleanQuery){
    Iterator<BooleanClause> clauses = ((BooleanQuery) q1).iterator();
    while (clauses.hasNext()) {
    BooleanClause clause = clauses.next();
    if (clause.getOccur() == Occur.MUST) {
    builder.add(clause);
    } else {
    builder.add(q1,Occur.MUST);
    }
}    

return builder.build();
}

5. 项目运行

打开包中的测试代码
1.IKAnalzyerDemo
运行结果如下图
输入图片说明

2.LuceneIndexAndSearchDemo 运行结果如下图

输入图片说明

6. 源码与整合包的下载

源码与整合包 已经上传至我的 GitHub 上,有兴趣的可以去那里下载,不嫌弃的话,Star 一下 ,也是可以的哦~

© 著作权归作者所有

共有 人打赏支持
柳初心
粉丝 0
博文 31
码字总数 15977
作品 0
南昌
私信 提问
Lucene 自定义分词

各位大神,帮菜鸟看个问题! 使用Lucene3.5版本以及 IKAnalyzer 分词, 在对IP字段(192.168.2.240)分词时,结果为 : 192.168.2.240;其他表字段同样采用IKAnalyzer 分词; 我的问题是:如何...

learn_more
2015/05/13
246
3
在Solr4.9中使用IKAnalyzer,实现同义词,扩展词库,停顿词的添加

在使用solr4.9的过程中,使用了IKAnalyzer分词器,其中遇到了不少问题,现在做个记录,以备后续只用。 首先使用IKAnalyzer是看到群里有人介绍,但是貌似现在IKAnalyzer已经没人更新了。。。不...

翊骷
2014/09/11
0
1
Lucene使用IKAnalyzer中文分词笔记

本文主要讲解IKAnalyzer(以下简称‘IK’)在Lucene中的具体使用,关于Lucene和IK分词器的背景及其作用在这里就不再熬述。不得不感叹下Lucene版本变更的快速,如今最新已经到了4.9.0,相信任...

Jialy
2014/09/02
0
0
关于Lucene全文检索中分析器Analyzer检索不到单个汉字的问题

在Java中运用Lucene全文检索功能,但是 分析器用过 CJKAnalyzer、 StandardAnalyzer、SimpleAnalyzer等,都无法对单个汉字进行检索,而且检索部分标点符号的时候也会报错,想问一下,有用过I...

夏可儿
2010/03/10
2.4K
11
IKAnalyzer分词器自定义扩展字典设置不起作用

IKAnalyzer配置如下: ext.dic是自定义扩展词库,我在里面添加了一项: 欧洲杯四强赛 希望IKAnalyzer能把它当作一个词,不要把它拆分,可是运行结果却是: 加载扩展词典:/ext.dic 加载扩展停止词典...

vnetoolxw
2014/03/29
9.6K
8

没有更多内容

加载失败,请刷新页面

加载更多

windows10小鹤双拼注册表

《安全第一》直接发文本内容,自己建文本,改文本后缀reg。 使用方法: 1.复制下示文本内容,打开你的文本编辑器(#记事本notepad或其他++),粘贴文本内容并保存在任意位置(不影响使用) ...

漫步海边小路
9分钟前
0
0
一、数据挖掘

数据挖掘的发展动力---需要是发明之母 数据爆炸问题 自动数据收集工具和成熟的数据库技术使得大量的数据被收集,存储在数据库、数据仓库或其他信息库中以待分析。我们拥有丰富的数据,但却缺...

凯文加内特
13分钟前
0
0
Java线程池ThreadPoolExecutor

线程池 ThreadPoolExecutor 线程池是ExecutorService的实现,可以通过Executors执行工厂构造不同类型的执行服务(线程池)。 ThreadPoolExecutor线程池使用的是阻塞队列BlockingQueue。 用于...

器石_
14分钟前
1
0
Mybatis 实现SQL拦截并在控制台打印SQL和参数

注:可以拦截sql 执行时间,优化sql。并打印sql 以及参数 第一步:创建类: SqlPrintInterceptor 并实现 Interceptor 该类如下: package com.ra.common.plugin;import org.apache.ibati...

轻量级赤影
17分钟前
1
0
Log4j2 配置

config: <?xml version="1.0" encoding="UTF-8"?><!-- http://logging.apache.org/log4j/2.x/manual/appenders.html --><!-- status 负责打印日记系统的 WARN 级别以及以上的日记 --><C......

Credo-Zhao
17分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部