lucene+ikanalyzer实现中文同义词搜索

lucene实现索引的创建与检索;ikanalyzer实现对中文的分词;光到这里已经能够实现中文的检索了,但是光这样还不够,很多项目中的检索,应该还能够对同义词进行处理,比如索引库中有“计算机”,“电脑”这样的词条,搜索“笔记本”应该也能把“计算机”,“电脑”这样的词条匹配出来,这就涉及到对同义词的索引检索了。

两种方案:

1、在建立索引时,拆词建索引时就把同义词考虑进去,将同义词的词条加入到索引中,然后检索时,直接根据输入拆词来检索

2、在建立索引时,不对同义词进行任何处理,在检索时,先拆词,针对拆分出来的词元(呵呵,自创的称呼)也即关键字,进行同义词匹配,把匹配好的同义词拼成一个新的关键字,搜索索引时根据此关键字来进行检索。

个人觉得,方案二更优于方案一,理由如下:在建立索引时,就处理同义词,一方面会增加索引库的容量,导致索引效率的降低;其次,如果后期对同义词进行了扩展,比如原来,一个单词有2个同义词,后面增加到3个,就需要对索引进行重建了,比较麻烦!

大致代码如下:

lucene版本:4.10.3,ikanalyzer:IKAnalyzer2012_hf.jar

lucene每个版本变化貌似蛮大啊,方法之类的都改了好多了,不知道大家有这种感觉没

创建索引:

/**
	* MyIndexer.java
	* V1.0
	* 2015-1-28-下午8:53:37
	* Copyright (c) 宜昌***有限公司-版权所有
	*/
package com.x.same;

import java.io.File;
import java.io.IOException;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.TextField;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.MergePolicy.OneMerge;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.lionsoul.jcseg.analyzer.JcsegAnalyzer4X;
import org.lionsoul.jcseg.core.JcsegTaskConfig;
import org.wltea.analyzer.lucene.IKAnalyzer;

/**
 * 此类描述的是:
 * @author yax 2015-1-28 下午8:53:37
 * @version v1.0
 */
public class MyIndexer {

	public static void createIndex(String indexPath) throws IOException{
		Directory directory = FSDirectory.open(new File(indexPath));
		Analyzer analyzer = new IKAnalyzer();

//		IKAnalyzer analyzer = new IKAnalyzer();
		IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_4_10_3, analyzer);
		IndexWriter indexWriter = new IndexWriter(directory, config);
		Document document1 = new Document();
		document1.add(new TextField("title", "thinkpad超极本笔记本中的战斗机", Store.YES));
		indexWriter.addDocument(document1);

		Document document2 = new Document();
		document2.add(new TextField("title", "用户可以在这里配置自己的扩展字典", Store.YES));
		indexWriter.addDocument(document2);

		Document document3 = new Document();
		document3.add(new TextField("title", "您可以参考分词器源码", Store.YES));
		indexWriter.addDocument(document3);

		Document document4 = new Document();
		document4.add(new TextField("title", "第一台计算机是美国军方定制,专门为了计算弹道和射击特性表面而研制的,承担开发任务的“莫尔小组”由四位科学家和工程师埃克特、莫克利、戈尔斯坦、博克斯组成。1946年这台计算机主要元器件采用的是电子管。该机使用了1500" +
												"个继电器,18800个电子管,占地170m2,重量重达30多吨,耗电150KW,造价48万美元。这台计算机每秒能完成5000次加法运算,400次乘法运算,比当时最快的计算工具快300倍,是继电器计算机的1000倍、手工计算的20万倍。" +
												"用今天的标准看,它是那样的“笨拙”和“低级”,其功能远不如一只掌上可编程计算器,但它使科学家们从复杂的计算中解脱出来,它的诞生标志着人类进入了一个崭新的信息革命时代。", Store.YES));
		indexWriter.addDocument(document4);
		indexWriter.close();
	}

}

同义词处理工具类:

/**
	* AnalyzerUtil.java
	* V1.0
	* 2015-1-28-下午8:42:24
	* Copyright (c) 宜昌**有限公司-版权所有
	*/
package com.x.same;

import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.core.WhitespaceAnalyzer;
import org.apache.lucene.analysis.synonym.SynonymFilterFactory;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.analysis.util.FilesystemResourceLoader;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.util.Version;
import org.wltea.analyzer.core.IKSegmenter;
import org.wltea.analyzer.core.Lexeme;
import org.wltea.analyzer.lucene.IKAnalyzer;

/**
 * 此类描述的是:
 * @author yax 2015-1-28 下午8:42:24
 * @version v1.0
 */
public class AnalyzerUtil {

	/**
	 *
	     * 此方法描述的是:进行中文拆分
	 */
	public static String analyzeChinese(String input, boolean userSmart) throws IOException{
		StringBuffer sb = new StringBuffer();
        StringReader reader = new StringReader(input.trim());
        IKSegmenter ikSeg = new IKSegmenter(reader, userSmart);// true 用智能分词 ,false细粒度
        for (Lexeme lexeme = ikSeg.next(); lexeme != null; lexeme = ikSeg.next()) {
        	sb.append(lexeme.getLexemeText()).append(" ");
        }
        return sb.toString();
	}

	/**
	 *
	     * 此方法描述的是:针对上面方法拆分后的词组进行同义词匹配,返回TokenStream
	 */
	public static TokenStream convertSynonym(String input) throws IOException{
        Version ver = Version.LUCENE_4_10_3;
        Map<String, String> filterArgs = new HashMap<String, String>();
        filterArgs.put("luceneMatchVersion", ver.toString());
        filterArgs.put("synonyms", "config/synonyms.txt");
        filterArgs.put("expand", "true");
        SynonymFilterFactory factory = new SynonymFilterFactory(filterArgs);
        factory.inform(new FilesystemResourceLoader());
        Analyzer whitespaceAnalyzer = new WhitespaceAnalyzer();
        TokenStream ts = factory.create(whitespaceAnalyzer.tokenStream("someField", input));
        return ts;
	}

	/**
	 *
	     * 此方法描述的是:将tokenstream拼成一个特地格式的字符串,交给IndexSearcher来处理
	 */
    public static String displayTokens(TokenStream ts) throws IOException
    {
    	StringBuffer sb = new StringBuffer();
        CharTermAttribute termAttr = ts.addAttribute(CharTermAttribute.class);
        ts.reset();
        while (ts.incrementToken())
        {
            String token = termAttr.toString();
            sb.append(token).append(" ");
            System.out.print(token+"|");
//            System.out.print(offsetAttribute.startOffset() + "-" + offsetAttribute.endOffset() + "[" + token + "] ");
        }
        System.out.println();
        ts.end();
        ts.close();
        return sb.toString();
    }

    public static void main(String[] args) {
    	String indexPath = "D:\\search\\test";
    	String input = "超级";
    	System.out.println("**********************");
		try {
			String result = displayTokens(convertSynonym(analyzeChinese(input, true)));
//			MyIndexer.createIndex(indexPath);
			List<String> docs = MySearcher.searchIndex(result, indexPath);
			for (String string : docs) {
				System.out.println(string);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

检索索引相关类:

/**
	* MySearcher.java
	* V1.0
	* 2015-1-28-下午9:02:32
	* Copyright (c) 宜昌**有限公司-版权所有
	*/
package com.x.same;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.core.WhitespaceAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.FSDirectory;
import org.lionsoul.jcseg.analyzer.JcsegAnalyzer4X;
import org.lionsoul.jcseg.core.JcsegTaskConfig;

/**
 * 此类描述的是:
 * @author yax 2015-1-28 下午9:02:32
 * @version v1.0
 */
public class MySearcher {

	public static List<String> searchIndex(String keyword, String indexPath) throws IOException, ParseException{
		List<String> result = new ArrayList<>();
		IndexSearcher indexSearcher = null;
		IndexReader indexReader = DirectoryReader.open(FSDirectory.open(new File(indexPath)));
		indexSearcher = new IndexSearcher(indexReader);
		Analyzer analyzer = new WhitespaceAnalyzer();

		QueryParser queryParser = new QueryParser("title", analyzer);
		Query query = queryParser.parse(keyword);
		TopDocs td = indexSearcher.search(query, 10);
		for (int i = 0; i < td.totalHits; i++) {
			Document document = indexSearcher.doc(td.scoreDocs[i].doc);
			result.add(document.get("title"));
		}
		return result;
	}

}

同义词文件格式:

我,俺,hankcs
似,is,are => 是
好人,好心人,热心人
超极本,计算机,电脑

第1、3、4行是同义词,第二行表示对似,is,are进行是的转换,即纠错功能

代码仅做参考,欢迎大家交流讨论指正。

转载请注明出处

时间: 2024-08-07 21:20:51

lucene+ikanalyzer实现中文同义词搜索的相关文章

Lucene实现自定义中文同义词分词器

---------------------------------------------------------- lucene的分词_中文分词介绍 ---------------------------------------------------------- Paoding:庖丁解牛分词器.已经没有更新了 mmseg:使用搜狗的词库 1.导入包(有两个包:1.带dic的,2.不带dic的) 如果使用不带dic的,得自己指定词库位置 2.创建MMSegAnalyzer(指明词库所在的位置

lucene+IKAnalyzer实现中文纯文本检索系统

首先IntelliJ IDEA中搭建Maven项目(web):spring+SpringMVC+Lucene+IKAnalyzer spring+SpringMVC搭建项目可以参考我的博客 整合Lucene 4.9.0 pom.xml添加lucene依赖 properties标签添加<lucene.version>4.9.0</lucene.version> dependencies添加: 1 <!-- lucene start --> 2 <dependency

Lucene实践之中文分词IKAalyzer

做检索怎么都绕不过中文分词去,学习一下用IKAnalyzer分词器做中文分词. Game Starts 参考文档 1) 中文分词之Java实现使用IK Analyzer实现 2) IKAnalyzer 独立使用 配置扩展词典 依赖jar包 1) IKAnalyzer2012FF_u1.jar 最好使用这个版本下面说 [百度网盘下载] 2) IKAnalyzer.cfg.xml [百度网盘下载] 3) keyWord.dic,stopWord.dic 字典 主要的类 1) IKAnalyzer ,

Sphinx + Coreseek 实现中文分词搜索

Sphinx + Coreseek 实现中文分词搜索 Sphinx Coreseek 实现中文分词搜索 全文检索 1 全文检索 vs 数据库 2 中文检索 vs 汉化检索 3 自建全文搜索与使用Google等第三方站点提供的站内全文搜索的差别 Sphinx Coreseek介绍 Coreseek安装使用 1. 全文检索 1.1 全文检索 vs. 数据库 全文检索是数据库的有力补充,全文检索并不能替代数据库在应用系统中的作用.当应用系统的数据以大量的文本信息为主时,採用全文检索技术能够极大的提升应

42、lucene和机器学习进行全文搜索,并排序

package com.lucene.test; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; i

IK 异常class org.wltea.analyzer.lucene.IKAnalyzer overrides final method tokenStream

在网上下载了lucene当前最新版本4.0,以及IKAnalyzer中文分词器的完整发布包. 运行之后发现异常:Exception in thread "main" java.lang.VerifyError: class org.wltea.analyzer.lucene.IKAnalyzer overrides final method tokenStream.(Ljava/lang/String;Ljava/io/Reader;)Lorg/apache/lucene/analys

IKAnalyzer进行中文分词和去停用词

最近学习主题模型pLSA.LDA,就想拿来试试中文.首先就是找文本进行切词.去停用词等预处理,这里我找了开源工具IKAnalyzer2012,下载地址:(:(注意:这里尽量下载最新版本,我这里用的IKAnalyzer2012.zip 这本版本后来测试时发现bug,这里建议IKAnalyzer2012_u6.zip)) https://code.google.com/p/ik-analyzer/ 由于太多,而且名称我也搞不清楚,不知道下载哪个.后来我下载了IKAnalyzer2012.zip 压缩

初识Lucene 4.5.0 全文搜索--(二)

上一篇文章初识Lucene 4.5.0--(一)已经介绍了如何创建索引与检索索引.接下来就是删除与更新啦~ 一.删除索引. 原本3.x版本时 IndexWriter 与 IndexReader 都是有删除方法的,让我们先来看看lucene 3.6 api文档中的IndexReader的描述: 从4.0开始已经被删除了,所以现在只能用IndexWriter中的方法来进行删除.有哪些方法呢?继续看文档(lucene 4.5 api): 除了上面的六个外还有一个方法tryDeleteDocument(

搜索引擎系列 ---lucene简介 创建索引和搜索初步

一.什么是Lucene? Lucene最初是由Doug Cutting开发的,2000年3月,发布第一个版本,是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎 :Lucene得名于Doug妻子的中名,同时这也她外祖母的姓;目前是Apache基金会的一个顶级项目,同时也是学习搜索引擎入门必知必会. Lucene 是一个 JAVA 搜索类库,它本身并不是一个完整的解决方案,需要额外的开发工作. 优点:成熟的解决方案,有很多的成功案例.apache 顶级项目,正在持续快速的进步.庞大而活跃的开