- 浏览: 288143 次
- 性别:
- 来自: 哈尔滨
-
文章分类
最新评论
-
netfengxia:
这个是Mybatis哦. 是一个ORM框架, 这里展示的是My ...
mybatis merge 语句使用 -
MILLETS:
好像没有效果
jsp页面打印、预览、设置实现方案 -
evic520:
mysql有merge into的用法?是不是标题错了 楼主? ...
mybatis merge 语句使用 -
winner_king:
解决问题
pager-taglib分页中文乱码问题 -
Renee涟漪:
...
SVN搭建
全文检索引擎Lucene
1. 信息检索的概念
从信息集合中找出与用户需求相关的信息。被检索的信息包括文本、图像、音频、视频等多媒体信息。
2. 信息检索的分类
全文检索:把用户的查询请求和全文的每一个词进行比较,不考虑查询请求与文本语义上的匹配。在信息检索工具中,全文检索是最具通用性和实用性的。(只搜索文本)
数据检索
知识检索
3. 全文检索流程
*从信息源中拷贝到本地进行加工,生成的信息集合称为索引表,搜索时从本地的信息集合中搜索
*文本在建立索引和搜索时都会先分词(使用分词器),且使用同一个分词器,不同的语言有不同的分词器
全文检索与数据库查询的比较:
1.匹配效果:如搜索ant,在sql中用like %ant% 会搜出planting 但它不应该出现
2.查出的结果没有相关度排序,不知道有用的结果在哪一页。
3.搜索速度慢,达不到毫秒级的要求
Lucene介绍与初步使用
Lucene是一个高性能、可伸缩的全文检索工具包。可以使用它为你的应用程序添加索引和搜索功能。
Lucene的作者Doug Cutting 是资深的全文检索专家。最初,Lucene以开源的形式出现在SourceForget上。2001年Lucene加入了Apache旗下的Jakarta项目。2005年,Lucene正式脱离Jakarta成为Apache旗下的顶级项目。现在,Lucene的主页为http://lucene.apache.org/
目前有很多应用程序使用Lucene来提供全文检索的功能,如Eclipse的帮助子系统就是使用Lucene实现的。
Lucene中对应的类:
Directory:索引库的位置,一般为一个目录
Document:信息集合中的每条数据。是field的集合
Field:是感兴趣的内容.
f1 = new Field(“title”,”xxxx”);//值为文本,如日期,数字要转型
f2 = new Field(“body”,”xxxx”);
doc.add(f1);
doc.add(f2);
Analyzer:分词器
IndexWriter:用来操作索引库的(增、删、改)
IndexSearcher:是用来在索引库中进行查询的
Query:查询对象,解析查询条件
分词器
分词器,对文本资源进行切分,将文本按规则切分为一个个可以进行索引的最小单位(关键词)
英文分词
分词流程:
输入文本à关键字切分à去除停用词à形态还原à转为小写
停用词:对文本所携带的信息基本不产生影响的词。如英文的“a, an,of,the”,中文的“的,了,着”。
例:对“IndexWriter addDocument’s a javadoc.txt”进行分词
1,切分词
IndexWriter addDocument’s a javadoc.txt
2,去除停用词
IndexWriter addDocument’s javadoc.txt
3,形态还原
IndexWriter addDocument javadoc.txt
4,转为小写
indexwriter adddocument javadoc.txt
中文分词
中文分词比较复杂,如“帽子和服装”。对于中文分词,通常有3种方式:单字分词(StandarAnalyzer)、二分法分词(CJKAnalyzer)、词典分词(MMAnalyzer)
例:net.hlj.lucene.analyzer.AnalyzerTest.java
下面写一个简单的 索引,检索程序 net.hlj.lucene.test.Test1.java
用到的jar包:
lucene-core-2.4.0.jar
lucene-analyzers-2.4.0.jar
je-analysis-1.5.3.jar
lucene-highlighter-2.4.0.jar
下载地址:http://archive.apache.org/dist/lucene/java/
IndexDao
完成对索引的增删改查
工具类DateTools、NumberTools
DateTools:转换日期的工具类,Resolution参数可以指定日期的精度。
NumberTools:转换数字的工具类,把数字转换为36进制的字符串
Highligher:高亮器
指定要高亮信息的前缀和后缀
查询:net.hlj.lucene.query.QueryTest.java
TermQuery:关键词查询
RangeQuery:范围查询
WildcardQuery:通配符查询
PhraseQuery:短语查询
BooleanQuery:布尔查询
排序
1相关度排序
Document的boost属性:Document.setBoost(float boost)
Field的boost属性:Field.setBoost(float boost)
查询时指定:MultFieldQueryParser(String[] fields,Analyzer analyzer,Map boosts)
2按指定字段排序
Public Sort(SortField field)
Public Sort(SortField[] fields)
过滤器
RangeFilter ,可以对搜索出来的结果进行过滤
性能优化
从优化创建索引性能和优化搜索性能两方面介绍
1 优化创建索引性能
IndexWriter提供了一些接口可以控制建立索引的操作,另外我们可以先将索引写入RAMDirectory,再批量写入FSDirectory,不管怎样,目的都是尽量少的文件IO,因为创建索引的最大瓶颈在于磁盘IO。另外选择一个较好的分析器也能提高一些性能。
通过设置IndexWriter的参数优化索引建立
setMaxBufferedDocs(int maxBufferedDocs)
控制写入一个新的segment前内存中保存的document的数目,设置较大的数目可以加快建索引速度,默认为10。
setMaxMergeDocs(int maxMergeDocs)
控制一个segment中可以保存的最大document数目,值较小有利于追加索引的速度,默认Integer.MAX_VALUE,无需修改。
setMergeFactor(int mergeFactor)
控制多个segment合并的频率,值较大时建立索引速度较快,默认是10,可以在建立索引时设置为100。
通过RAMDirectory缓写提高性能
我们可以先把索引写入RAMDirectory,达到一定数量时再批量写进FSDirectory,减少磁盘IO次数。
FSDirectory fsDir = FSDirectory.getDirectory("/data/index", true);
RAMDirectory ramDir = new RAMDirectory();
IndexWriter fsWriter = new IndexWriter(fsDir, new StandardAnalyzer(), true);
IndexWriter ramWriter = new IndexWriter(ramDir, new StandardAnalyzer(), true);
Int i=0;
while (there are documents to index)
{
... create Document ...
ramWriter.addDocument(doc);
if (i==100)
{
fsWriter.addIndexes(new Directory[] { ramDir });
ramWriter.close();
ramWriter = new IndexWriter(ramDir, new StandardAnalyzer(), true);
i=0;
}
i++;
}
选择较好的分词器
相同测试数据下由600M减少到380M,但是耗时长,时间换空间。
2 优化搜索性能
将索引放入内存
这是一个最直观的想法,因为内存比磁盘快很多。Lucene提供了RAMDirectory可以在内存中容纳索引:
Directory fsDir = FSDirectory.getDirectory(“/data/index/”, false);
Directory ramDir = new RAMDirectory(fsDir);
Searcher searcher = new IndexSearcher(ramDir);
优化时间范围限制
既然载入内存并不能提高效率,一定有其它瓶颈,经过测试发现最大的瓶颈居然是时间范围限制,那么我们可以怎样使时间范围限制的代价最小呢?
当需要搜索指定时间范围内的结果时,可以:
1、用RangeQuery,设置范围,但是RangeQuery的实现实际上是将时间范围内的时间点展开,组成一个个BooleanClause加入到 BooleanQuery中查询,因此时间范围不可能设置太大,经测试,范围超过一个月就会抛BooleanQuery.TooManyClauses,可以通过设置 BooleanQuery.setMaxClauseCount(int maxClauseCount)扩大,但是扩大也是有限的,并且随着maxClauseCount扩大,占用内存也扩大
2、用RangeFilter代替RangeQuery,经测试速度不会比RangeQuery慢,但是仍然有性能瓶颈,查询的90%以上时间耗费在 RangeFilter,研究其源码发现RangeFilter实际上是首先遍历所有索引,生成一个BitSet,标记每个document,在时间范围内的标记为true,不在的标记为false,然后将结果传递给Searcher查找,这是十分耗时的。
3、进一步提高性能,这个又有两个思路:
a、缓存Filter结果。既然RangeFilter的执行是在搜索之前,那么它的输入都是一定的,就是IndexReader,而 IndexReader是由Directory决定的,所以可以认为RangeFilter的结果是由范围的上下限决定的,也就是由具体的 RangeFilter对象决定,所以我们只要以RangeFilter对象为键,将filter结果BitSet缓存起来即可。lucene API已经提供了一个CachingWrapperFilter类封装了Filter及其结果,所以具体实施起来我们可以cache CachingWrapperFilter对象,需要注意的是,不要被CachingWrapperFilter的名字及其说明误导, CachingWrapperFilter看起来是有缓存功能,但的缓存是针对同一个filter的,也就是在你用同一个filter过滤不同 IndexReader时,它可以帮你缓存不同IndexReader的结果,而我们的需求恰恰相反,我们是用不同filter过滤同一个 IndexReader,所以只能把它作为一个封装类。
b、降低时间精度。研究Filter的工作原理可以看出,它每次工作都是遍历整个索引的,所以时间粒度越大,对比越快,搜索时间越短,在不影响功能的情况下,时间精度越低越好,有时甚至牺牲一点精度也值得,当然最好的情况是根本不作时间限制。
下面针对上面的两个思路演示一下优化结果(都采用800线程随机关键词随即时间范围):
第一组,时间精度为秒:
方式 直接用RangeFilter 使用cache 不用filter
平均每个线程耗时 10s 1s 300ms
第二组,时间精度为天
方式 直接用RangeFilter 使用cache 不用filter
平均每个线程耗时 900ms 360ms 300ms
由以上数据可以得出结论:
1、 尽量降低时间精度,将精度由秒换成天带来的性能提高甚至比使用cache还好,最好不使用filter。
2、 在不能降低时间精度的情况下,使用cache能带了10倍左右的性能提高。
3、使用更好的分词器
发表评论
-
jsp中配置 FCKeditor2.3(转)
2013-07-24 14:56 1194现在已经升级成CKeditor了 不过这方面的教程不是很多, ... -
fck配置
2013-07-24 13:58 8701.下载两个包,分别是java下的Servlet和FCK的H ... -
页面超时返回,登陆页面被iframe嵌套问题
2012-05-25 17:01 1426if(window.top.location.href!=lo ... -
pager-taglib分页中文乱码问题
2012-02-13 11:32 3973问题:整个项目是struts2+spring,页面编码格式ut ... -
jsp 用urlrewrite 实现URL 重写
2011-12-30 16:51 1685下面是使用说明: 1.下载urlrewrite,官方下载地 ... -
页面显示html代码
2011-11-07 17:43 974先有方法1 ,<xmp>标签。。。但是会撑破风格。 ... -
JS限制图片大小并自动缩放
2011-09-19 15:37 1476//限制产品内容图片大小,自动缩放 function aut ... -
css超级链接保持原色
2011-09-19 10:39 1229.nav01 a:link { text-decorati ... -
Java获取客户端真实IP地址的两种方法
2011-07-25 15:06 6460在JSP里,获取客户端的IP地址的方法是:request.ge ... -
路由诊断命令tracert
2011-06-09 14:25 965tracert xxx.xxx.xxx.xxx -
锚点定位例子
2011-04-13 15:58 1264<!DOCTYPE HTML PUBLIC &qu ... -
iframe重新加载
2011-03-24 16:25 1304document.frames('iframesid') ... -
网站2侧广告js实现
2011-01-13 16:51 1023<script language="javas ... -
jsp页面打印、预览、设置实现方案
2010-12-02 10:29 118881 、print.jsp <%@ page langu ... -
Window.open() 全攻略
2010-12-02 10:06 1003经常上网的朋友可能会到过这样一些网站,一进入首页立刻会弹出一个 ... -
(转)自动检测密码强度的一个小例子
2010-11-16 11:28 1362检测密码强度Demo.html: <html> ... -
鼠标变“小手”的样式
2010-10-29 14:41 1795//鼠标变“小手”的样式 { cursor:p ...
相关推荐
开放源代码的全文检索引擎Lucene开放源代码的全文检索引擎Lucene开放源代码的全文检索引擎Lucene
### 全文检索引擎Lucene知识点详解 #### 1. 全文检索系统与Lucene简介 ##### 1.1 全文检索与全文检索系统定义 全文检索是指计算机索引程序通过对文章中的每一个词建立索引,记录其在文章中的出现次数和位置,以...
**Lucene全文检索引擎** Lucene是Apache软件基金会的一个开源项目,它是一个高性能、全文本搜索引擎库,可以被集成到各种应用中实现全文检索功能。Lucene提供了完整的搜索功能实现,包括索引创建、文档存储、查询...
### Java全文检索引擎Lucene的应用 #### 一、引言 随着信息技术的飞速发展,尤其是数据库技术和数据库管理系统(DBMS)的广泛应用,全球范围内的数据量急剧增长。特别是在科学研究领域,面对海量的数据,传统的手工...
《开放源代码的全文检索引擎Lucene终稿》是一份深度解析开源全文检索引擎Lucene的文档,旨在介绍Lucene的基本概念、系统架构以及源码实现。全文主要分为四个部分,详细阐述了Lucene的核心技术和应用。 在第一部分,...
全文搜索引擎Lucene是Apache软件基金会的一个开放源代码项目,它为Java开发者提供了一个高性能、可扩展的信息检索库。Lucene以其强大的文本搜索功能和高效的索引能力,在各种需要全文检索的应用场景中被广泛采用。...
《开放源代码的全文检索引擎Lucene收集》 全文检索系统是互联网信息处理的重要工具,它使得用户可以高效地在海量数据中查找相关信息。Lucene是Apache软件基金会下的一个开放源代码项目,它为开发者提供了强大的全文...
**全文检索引擎Lucene** Lucene是一个开源的全文检索库,由Apache软件基金会维护。它提供了文本分析、索引创建、搜索以及相关的工具,旨在帮助开发者构建强大的搜索功能。在这个项目中,Lucene被用于创建一个简易的...
Java全文搜索引擎Lucene是Apache软件基金会的一个开源项目,它为开发者提供了一个强大的、高性能的、可扩展的全文检索工具包。Lucene的核心功能包括文本分析、索引创建、查询解析和搜索结果的排序。它不是预包装的...
### 基于Java的全文检索引擎Lucene的分析与研究 #### 一、Lucene简介 Lucene是一个用Java编写的全文检索引擎工具包,它由Doug Cutting创建,并作为Apache Jakarta项目的一部分开源。尽管Lucene本身不是一个完整的...
它的设计目标是为开发人员提供一个易于使用的工具,以便在自己的应用程序中集成全文检索功能,或者构建基于 Lucene 的完整搜索引擎。 【全文检索系统基础】 全文检索系统是基于全文检索理论建立的软件系统,其基本...
【Lucene教程(全文搜索引擎)】 Lucene是一个强大的开源全文搜索库,由Apache软件基金会维护。作为信息检索(IR)的框架,它提供了一个高效、可扩展的基础来构建搜索引擎和其他涉及文本检索的应用程序。不同于可以...
Lucene的创始人Doug Cutting是一位在全文索引和检索领域有着深厚经验的专家,他曾在V-Twin搜索引擎和Excite担任重要角色。Lucene起初是在作者个人网站发布,后来成为Apache开源项目的一部分。 【全文检索和Lucene的...
Java全职搜索引擎Lucene是一个强大的开源工具,用于创建高效的全文索引和搜索功能。它由Apache软件基金会维护,被广泛应用于各种网站和应用程序中,以提供快速、精准的站内搜索体验。本教程将深入讲解如何使用Lucene...