热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

搜索为将IKAnalyzerlucene6.6适配

前言在中文分词器中,IKAnalyzer做的是相对不错的,有着细度分割和智能使用两个模式。但是,这个版本因为太陈旧,作者不再维护,(项目估计是。。。),所以与现在的Lucene6.

前言

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

正文

项目介绍

  1. IKAnaylzer版本: IK Analyzer 2012FF

感谢提供的分词源码 http://git.oschina.net/wltea/…

  1. 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 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
运行结果如下图

《搜索为将 -- IKAnalyzer -- lucene6.6适配》
2.LuceneIndexAndSearchDemo
运行结果如下图

《搜索为将 -- IKAnalyzer -- lucene6.6适配》

5. 源码与整合包的下载

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


推荐阅读
  • 编译原理中的语法分析方法探讨
    本文探讨了在编译原理课程中遇到的复杂文法问题,特别是当使用SLR(1)文法时遇到的多重规约与移进冲突。文章讨论了可能的解决策略,包括递归下降解析、运算符优先级解析等,并提供了相关示例。 ... [详细]
  • 本文主要解决了在编译CM10.2时出现的关于Samsung Exynos 4 HDMI HAL库中SecHdmiV4L2Utils.cpp文件的编译错误。 ... [详细]
  • 本文详细介绍了如何在本地环境中安装配置Frida及其服务器组件,以及如何通过Frida进行基本的应用程序动态分析,包括获取应用版本和加载的类信息。 ... [详细]
  • 本文介绍了两个重要的Node.js库——cache-content-type和mime-types,它们在处理HTTP响应头时非常有用。cache-content-type是基于mime-types构建的,并且实现了缓存机制以提高性能。 ... [详细]
  • 本文详细介绍了`android.os.Binder.getCallingPid()`方法的功能和应用场景,并提供了多个实际的代码示例。通过这些示例,开发者可以更好地理解如何在不同的开发场景中使用该方法。 ... [详细]
  • Python Requests模块中的身份验证机制
    随着Web服务的发展,身份验证成为了确保数据安全的重要环节。本文将详细介绍如何利用Python的Requests库实现不同类型的HTTP身份验证,包括基本身份验证、摘要式身份验证以及OAuth 1认证等。 ... [详细]
  • Activity跳转动画 无缝衔接
    Activity跳转动画 无缝衔接 ... [详细]
  • 字符、字符串和文本的处理之Char类型
    .NetFramework中处理字符和字符串的主要有以下这么几个类:(1)、System.Char类一基础字符串处理类(2)、System.String类一处理不可变的字符串(一经 ... [详细]
  • 本文详细探讨了 Java 中 com.codahale.metrics.servlets.AdminServlet.() 方法的实现与应用,并提供了多个实际项目中的代码示例,帮助开发者更好地理解和使用这一方法。 ... [详细]
  • [编程题] LeetCode上的Dynamic Programming(动态规划)类型的题目
    继上次把backTracking的题目做了一下之后:backTracking,我把LeetCode的动态规划的题目又做了一下,还有几道比较难的Medium的题和Hard的题没做出来,后面会继续 ... [详细]
  • 本文探讨了 Boost 库中的 Program Options 组件,这是一个强大的工具,用于解析命令行参数和配置文件。文章介绍了如何正确设置和使用该组件,包括处理复杂选项和负数值的方法。 ... [详细]
  • 本书《Pro Git》深入探讨了 Git 版本控制系统的核心概念与高级功能,旨在帮助开发者和团队有效管理代码变更。通过实例和最佳实践,读者将学习如何利用 Git 提升工作效率。 ... [详细]
  • 本文基于《Core Java Volume 2》的内容,深入探讨了网络编程中通过POST方法提交表单数据的技术细节,包括GET与POST方法的区别、POST提交的具体步骤及常见问题处理。 ... [详细]
  • 深入解析轻量级数据库 SQL Server Express LocalDB
    本文详细介绍了 SQL Server Express LocalDB,这是一种轻量级的本地 T-SQL 数据库解决方案,特别适合开发环境使用。文章还探讨了 LocalDB 与其他轻量级数据库的对比,并提供了安装和连接 LocalDB 的步骤。 ... [详细]
  • 在尝试使用 Android 发送 SOAP 请求时遇到错误,服务器返回 '无法处理请求' 的信息,并指出某个值不能为 null。本文探讨了可能的原因及解决方案。 ... [详细]
author-avatar
支持骸云
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有