`
yangwei0915
  • 浏览: 459956 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

Lucene学习之中文查询问题的解决

 
阅读更多

在构建文档库之后,绝大多数的查询都是基于中文进行查询。使用前面的例子,进行测试时,会发现这样问题:

使用关键词“微信”进行搜索时,能够搜索到没有“微信”这个词出现,但是有“微”和“信”这两个字出现的文档。造成这种错误搜索的原因是,Lucene标准的分析器在分析文档以及查询关键词时,对于英文是基于单词分词的,但是对于中文,是基于汉字进行分词的,所以就造成了上述的查询问题。为了解决这个问题,我们只需要将Lucene的标准分析器换成中文的分析器就可以了,IK Analyzer基于lucene实现的分词开源框架具有如下特性:

 

  • 算法采用“正向迭代最细粒度切分算法”, 支持细粒度和最大词长两种分词 方式,速度最大支持 80W 字/秒(1600KB/秒) 。
  •  支持多子处理器分析模式:中文、数字、字母,并兼容日文、韩文。
  • 较小的内存占用,优化词库占有空间,用户可自定义扩展词库。 采用歧义分析算法优化查询关键字的搜索排列组
  •  基于lucene 的扩展实现,提高 lucene 检索命中率。

比如对于“基于java语言开发的轻量级的中文分词工具包”,使用IK Analyzer分析后的结果为:

基于|java|语言|开发|的|轻量级|的|中文|分词|工具包|

基本上符合中文的分词,而使用Lucene标准的分析器,则分析的结果就是逐字分开。所以使用IK Analyzer作为分析器构建中文文档库时,不但能减少索引文件大小,还可以加快搜索速度。在使用时,只需要将构建索引时和查询时的分析器修改为IK Analyzer,就可以了。使用步骤如下: 

 

1.在http://code.google.com/p/ik-analyzer/downloads/list下载IK Analyzer 2012FF_hf1.zip(该版本与

   Lucene4.x兼容)

2.解压下载文件在classpath加入IKAnalyzer2012FF_u1.jar,并且将stopword.dic和IKAnalyzer.cfg.xml文件

   添加到src的根路径下(保证编译时这两个文件copy到classes的根路径下)。

3.在代码中使用IK Analyzer作为分析器

 

代码如下,为了便于调试,此处将全部代码贴出:

 

package com.hsdl.lucene;

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

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
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.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.store.LockObtainFailedException;
import org.apache.lucene.util.Version;
import org.apache.tika.Tika;
import org.wltea.analyzer.lucene.IKAnalyzer;

public class LuceneDemo2 {
	private static String contentFieldName = "content";
	private static Tika tika = new Tika();
	public static void main(String[] args) {
		//Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_45);
		//使用IKAnalyzer构建分析器
		Analyzer analyzer = new IKAnalyzer(true);
		try {
			String docPath = "D:/work/lucene/tika/doc";
			String indexPath = "D:/work/lucene/tika/index";
			//创建索引
			createIndex(analyzer, indexPath, docPath);
			//搜索
			search(analyzer, indexPath, "微信");
		} catch (CorruptIndexException e) {
			e.printStackTrace();
		} catch (LockObtainFailedException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
	}

	/**
	 * 创建索引
	 * 
	 * @param analyzer
	 * @param indexPath
	 * @param docPath
	 * @throws IOException
	 * @throws CorruptIndexException
	 * @throws LockObtainFailedException
	 */
	private static void createIndex(Analyzer analyzer, String indexPath,
			String docPath) throws IOException, CorruptIndexException,
			LockObtainFailedException {
		IndexWriter iwriter;
		Directory directory = FSDirectory.open(new File(indexPath));
		// 配置IndexWriterConfig
		IndexWriterConfig iwConfig = new IndexWriterConfig(Version.LUCENE_45,
				analyzer);
		iwConfig.setOpenMode(OpenMode.CREATE_OR_APPEND);
		iwriter = new IndexWriter(directory, iwConfig);
		File file = new File(docPath);
		indexDocs(iwriter, file);
		iwriter.close();
	}

	/**
	 * 搜索
	 * 
	 * @param analyzer
	 * @param indexPath
	 * @param queryStr
	 * @throws CorruptIndexException
	 * @throws IOException
	 * @throws ParseException
	 */
	private static void search(Analyzer analyzer, String indexPath,
			String queryStr) throws CorruptIndexException, IOException,
			ParseException {
		Directory directory = FSDirectory.open(new File(indexPath));
		// 搜索过程**********************************
		// 实例化搜索器
		IndexReader ireader = DirectoryReader.open(directory);
		IndexSearcher isearcher = new IndexSearcher(ireader);

		// 使用QueryParser查询分析器构造Query对象
		QueryParser qp = new QueryParser(Version.LUCENE_45, contentFieldName, analyzer);
		qp.setDefaultOperator(QueryParser.AND_OPERATOR);
		Query query = qp.parse(queryStr);

		// 搜索相似度最高的5条记录
		TopDocs topDocs = isearcher.search(query, 10);
		System.out.println("命中:" + topDocs.totalHits);
		// 输出结果
		ScoreDoc[] scoreDocs = topDocs.scoreDocs;
		System.out.println(scoreDocs.length);
		for (int i = 0; i < scoreDocs.length; i++) {
			Document targetDoc = isearcher.doc(scoreDocs[i].doc);
			System.out.println("内容:" + targetDoc.toString());
			System.out.println(targetDoc.get("fileName") + "["
					+ targetDoc.get("path") + "]");
		}
	}
	/**
	 * 根据指定存放内容的文件或目录创建索引
	 * @param iwriter
	 * @param file
	 * @throws IOException
	 */
	public static void indexDocs(IndexWriter iwriter, File file) throws IOException {
		if (file.canRead())
			if (file.isDirectory()) {
				String[] files = file.list();

				if (files != null)
					for (int i = 0; i < files.length; i++)
						indexDocs(iwriter, new File(file, files[i]));
			} else {
				Document doc = null;
				FileInputStream fis=null;
				try {
					doc = new Document();
					doc.add(new StringField("ID", "10000", Field.Store.YES));
					fis = new FileInputStream(file);
					//此处添加文件内容时,需要根据tika获取Reader对象
					doc.add(new TextField(contentFieldName, tika.parse(file)));
					doc.add(new StringField("fileName", file.getName(),
							Field.Store.YES));
					doc.add(new StringField("path", file.getAbsolutePath(),
							Field.Store.YES));
					iwriter.addDocument(doc);
				} finally {
					if(fis!=null){
						fis.close();
					}
				}
			}
	}
}

 

分享到:
评论

相关推荐

    解密搜索引擎技术实战-Lucene&java;精华版

    自然语言处理部分从统计机器学习的原理出发,包括了中文分词与词性标注的理论与实现及在搜索引擎中的应用等细节,同时对文档排重、文本分类、自动聚类、句法分析树、拼写检查等自然语言处理领域的经典问题进行了深入...

    1.解密搜索引擎技术实战:Lucene&Java;精华版(第3版)

    自然语言处理部分从统计机器学习的原理出发,包括了中文分词与词性标注的理论与实现及在搜索引擎中的应用等细节,同时对文档排重、文本分类、自动聚类、句法分析树、拼写检查等自然语言处理领域的经典问题进行了深入...

    淘特站内搜索引擎(C#版) v3.3

    淘特站内搜索引擎是由淘特JSP搜索引擎发展而来,系统基于Lucene.Net核心,通过高效的中文分词算法将数据库中内容进行分析、索引并保存至硬盘中。前台搜索时,通过读取索引文件查询,避免了传统数据库查询在高并发及...

    C# 盘古分词

    4、 增加优先优先词频选项,通过这个选项动态决定分词粒度 需打开 FreqFirst 5、 增加中文人名前后缀统计和根据该统计定位人名的功能 6、 增加中文人名和未登录词出现频率统计功能 7、 增加自动更新字典功能,对...

    淘特站内搜索引擎(C#版) 3.3

    淘特站内搜索引擎(C#版)基于Lucene.Net核心,通过高效的中文分词算法将数据库中内容进行分析、索引并保存至硬盘中。前台搜索时,通过读取索引文件查询,避免了传统数据库查询在高并发及海量数据下的性能问题。因前台...

    jive.chm

    4 Jive的中文问题及解决办法 5 Java程序的国际化和本地化介绍 6 Java的i18n问题 7 Java国际化——资源包的使用 8 国际化 9 Supported Encodings 10 native2ascii - Native-to-...

    Jive资料集

    13 Jive3.0.8 MYSQL的中文解决方案 14 jive_kb_i18n_zh_CN_ori.properties &lt;br&gt;&lt;br&gt; &lt;br&gt; &lt;br&gt;全文搜索 1 使您的Jive搜索支持中文 2 关于Jive2中的中文搜索 3 基于JAVA的全文索引引擎Lucene简介 ...

    Eclipse开发分布式商城系统+完整视频代码及文档

    解决火狐兼容性问题.avi │ 14.spring的父子容器.avi │ 淘淘商城第三天笔记.docx │ ├─04.第四天 │ 01.第三天内容复习.avi │ 02.课程计划.avi │ 03.富文本编辑器的使用.avi │ 04.商品添加功能-分析.avi │ ...

    JAVA上百实例源码以及开源项目源代码

    5个目标文件,演示Address EJB的实现,创建一个EJB测试客户端,得到名字上下文,查询jndi名,通过强制转型得到Home接口,getInitialContext()函数返回一个经过初始化的上下文,用client的getHome()函数调用Home接口...

    JAVA上百实例源码以及开源项目

    笔者当初为了学习JAVA,收集了很多经典源码,源码难易程度分为初级、中级、高级等,详情看源码列表,需要的可以直接下载! 这些源码反映了那时那景笔者对未来的盲目,对代码的热情、执着,对IT的憧憬、向往!此时此...

    ebsite for net4.0网站建设系统 v3.0 正式版.zip

    解决了微网站(web app)下的图片浏览体验及流量节省问题。 14.增加了"是否开启搜索关键词跟踪"功能,可以跟踪用户在你网站搜索了哪些关键词及搜索频率。您可以了解你的用户喜欢什么,为您的网站策划提供基础数据。 ...

Global site tag (gtag.js) - Google Analytics