??xml version="1.0" encoding="utf-8" standalone="yes"?>国产永久av在线,韩日一区二区,校园春色亚洲色图 http://www.aygfsteel.com/super2/category/35589.html潇洒的一条犬 zh-cn Thu, 30 Oct 2008 03:48:29 GMT Thu, 30 Oct 2008 03:48:29 GMT 60 [转]lucene学习W记十二 -- l果内容昄的文本数?/title> http://www.aygfsteel.com/super2/archive/2008/10/29/237309.html淘声依旧 淘声依旧 Wed, 29 Oct 2008 02:08:00 GMT http://www.aygfsteel.com/super2/archive/2008/10/29/237309.html http://www.aygfsteel.com/super2/comments/237309.html http://www.aygfsteel.com/super2/archive/2008/10/29/237309.html#Feedback 0 http://www.aygfsteel.com/super2/comments/commentRss/237309.html http://www.aygfsteel.com/super2/services/trackbacks/237309.html
q个控制昄的结果数量多?
l果展现:
String result= highlighter.getBestFragment(tokenStream, hits.doc(i).get("key"));
]]> [转]lucene学习W记?-- 关于高亮昄和显C部分原始文件的原则 http://www.aygfsteel.com/super2/archive/2008/10/29/237306.html淘声依旧 淘声依旧 Wed, 29 Oct 2008 02:06:00 GMT http://www.aygfsteel.com/super2/archive/2008/10/29/237306.html http://www.aygfsteel.com/super2/comments/237306.html http://www.aygfsteel.com/super2/archive/2008/10/29/237306.html#Feedback 0 http://www.aygfsteel.com/super2/comments/commentRss/237306.html http://www.aygfsteel.com/super2/services/trackbacks/237306.html
有一个能使搜索引擎变得更友好的办法,那就是向你的用户提供一些搜索命中结果的上下文,而且更ؓ重要的是q样做是非常有用
的。最好的例子是本系l用户在查找天气Web服务时的搜烦l果。如下图1所C,每个命中l果包括了匹配文档的三行左右的内容,q且查询项高亮昄?
来。通常Q我们只需要对搜烦?上下文内Ҏ(gu)览一眼就以 了解该结果是否值得我们深入地进行研I?br />
?.1 高亮昄查询?br />
Highlighter
最q已l充分升Uؓ一个复杂而灵zȝ工具。Highlighter包括了三个主要部分:D划分器QFragmenterQ、计分器QScorerQ和格式
化器QFormatterQ。这几个部分对应于Java的同名接口,q且每部分都有一个内|的实现以便我们使用。最单的Highlighter返回在
匚w周围的最x落,q用HTML?lt;B>这些项标记出来Q?br />
String text = “The quick brown fox jumps over the lazy dog”;
TermQuery query = new TermQuery(new Term(“field”, “fox”));
Scorer scorer = new QueryScorer(query);
Highlighter highlighter = new Highlighter(scorer);
TokenStream tokenStream =
new SimpleAnalyzer().tokenStream(“field”,
new StringReader(text));
System.out.println(highlighter.getBestFragment(tokenStream,text));
前述代码生如下输?br />
The quick brown <B>fox</B> jumps over the lazy dog
Highlighter不仅需要你提供记分器和需要高亮显C的文本Q还需要一个TokenStream实例。这个TokenStream实例是由分析器生
成的。ؓ了成功地寚wq行高亮昄QQuery中的q些w要匹配TokenStream产生的Token实例。我们提供的文本则被用于生成
TokenStreamQ而这个TokenStream又被用作高亮昄的原始文本。每个由TokenStream生成的Token实例都包含语汇单元的
位置信息Q这些信息用来指C原始文本中高亮部分的v始和l束位置?
Highlighter利用Fragmenter原始文本分割成多个片段。内|的SimpleFragmenter原始文本分割成相同大小的片D,片段默认的大ؓ100个字W。这个大是可控制的?br />
QueryScorer是内|的计分器。计分器的工作首先是片D|序。QueryScorer使用的项是从用户输入的查询中得到的;它会从原始输入的?
词、词l和布尔查询中提取项Qƈ且基于相应的加权因子Qboost
factorQ给它们加权。ؓ了便于QueryScoere使用Q还必须Ҏ(gu)询的原始形式q行重写。比如,带通配W查询、模p查询、前~查询以及范围查询
{,都被重写为BoolenaQuery中所使用的项。在Query实例传递到QueryScorer之前Q可以调?
Query.rewrite(IndexReader)Ҏ(gu)来重写Query对象Q否则,你必ȝ保用戯入的查询文本是Lucene直接可以处理最?
本的)?br />
最后,格式化器QFormatterQ用于装饰项文本。如果不指定其他的格式化器,Lucene会默认用内|的格式化器
SimpleHTMLFormatterQ这个格式化器将会用HTML的黑体开始标{(begin bold tags
<B>Q和黑体l束标签Qend bold tags
</B>Q来标识出高亮显C的Ҏ(gu)本。Highlighter默认C用SimpleHTMLFormatter?
SimpleFragmenterq两个格式化器。每一个由Formatter高亮昄的项都将会带有一个语汇单元评分。当使用QueryScorer
Ӟq个评分作为查询该的加权因子。这个语汇单元评分能够被用来军_该项的重要性。要利用q个Ҏ(gu)就必须实现自定义的格式化器?br />
注:我们目所用到?Lucene
API是基于最新版Lucene2.1的,如果你用的是以前版本可能q些例子不能很好的运行。不q我觉得看了以上的东西,再结合网上大量的Lucene?
料还有一些例子就能对Lucene有一定的理解了,最L可以开始用Lucene着手项目了?br />
另外Q在文章开始提CQ我们以前一起做目时没有用过LuceneQ这ơ是我们团队的n宁同学开始接触LuceneQ然后在我们目中用这个工P
我是在他指导的基上对Lucene有一点点的理解而已。感兴趣的可以就目中的更细节问题跟赵宁同学联系QMSN:program-
maker@hotmail.com
]]> [转]lucene学习W记十一 -- 建烦引优?复杂排序HitCollector,匚w法 http://www.aygfsteel.com/super2/archive/2008/10/29/237307.html淘声依旧 淘声依旧 Wed, 29 Oct 2008 02:06:00 GMT http://www.aygfsteel.com/super2/archive/2008/10/29/237307.html http://www.aygfsteel.com/super2/comments/237307.html http://www.aygfsteel.com/super2/archive/2008/10/29/237307.html#Feedback 0 http://www.aygfsteel.com/super2/comments/commentRss/237307.html http://www.aygfsteel.com/super2/services/trackbacks/237307.html
/**
*
在IndexWriter中有一个MERGE_FACTOR参数可以帮助你在构造烦引器后根据应用环境的情况充分利用内存减少文g的操作。根据我的用经
验:~省Indexer是每20条记录烦引后写入一ơ,每将MERGE_FACTOR增加50倍,索引速度可以提高1倍左叟?br />
*/
indexWriter.setMergeFactor(1000);
2, 排序
« ?汉化 ?国际?| (回到Blog入口)|(回到首页) | Resin学习W记 »
LuceneQ基于Java的全文检索引擎简?br />
作者:车东 发表于:2002-08-06 18:08 最后更CQ?007-04-12 11:04
版权声明Q可以Q意{载,转蝲时请务必以超链接形式标明文章原始出处和作者信息及本声明?br />
http://www.chedong.com/tech/lucene.html
--------------------------------------------------------------------------------
Lucene是一个基于Java的全文烦引工具包?br />
ZJava的全文烦引引擎Lucene介:关于作者和Lucene的历?
全文索的实现QLuene全文索引和数据库索引的比?
中文切分词机制简介:Z词库和自动切分词法的比?
具体的安装和使用介:pȝl构介绍和演C?
Hacking LuceneQ简化的查询分析器,删除的实玎ͼ定制的排序,应用接口的扩?
从Lucene我们q可以学C?
ZJava的全文烦?索引擎——Lucene
Lucene不是一个完整的全文索引应用Q而是是一个用Java写的全文索引引擎工具包,它可以方便的嵌入到各U应用中实现针对应用的全文烦?索功能?br />
Lucene的作者:Lucene的A献者Doug
Cutting是一位资深全文烦?索专Ӟ曄是V-Twin搜烦引擎(Apple的Copland操作pȝ的成׃一)的主要开发者,后在
Excite担Q高pȝ架构设计师,目前从事于一些INTERNET底层架构的研I。他贡献出的Lucene的目标是为各U中型应用E序加入全文?
功能?br />
Lucene的发展历E:早先发布在作者自qwww.lucene.comQ后来发布在SourceForgeQ?001q年底成为APACHE基金?
jakarta的一个子目Qhttp://jakarta.apache.org/lucene/
已经有很多Java目都用了Lucene作ؓ其后台的全文索引引擎Q比较著名的有:
JiveQWEB论坛pȝQ?
EyebrowsQ邮件列表HTML归档/览/查询pȝQ本文的主要参考文?#8220;TheLucene search engine:
Powerful, flexible, and
free”作者就是EyeBrowspȝ的主要开发者之一Q而EyeBrows已经成ؓ目前APACHE目的主要邮件列表归档系l?
Cocoon:ZXML的web发布框架Q全文检索部分用了Lucene
Eclipse:ZJava的开攑ּ发^収ͼ帮助部分的全文烦引用了Lucene
对于中文用户来说Q最兛_的问题是其是否支持中文的全文索。但通过后面对于Lucene的结构的介绍Q你会了解到׃Lucene良好架构设计Q对中文的支持只需对其语言词法分析接口q行扩展p实现对中文检索的支持?br />
全文索的实现机制
Lucene的API接口设计的比较通用Q输入输出结构都很像数据库的?=>记录==>字段Q所以很多传l的应用的文件、数据库{都可以?
较方便的映射到Lucene的存储结?接口中。M上看Q可以先把Lucene当成一个支持全文烦引的数据库系l?br />
比较一下Lucene和数据库Q?br />
Lucene 数据?
索引数据源:doc(field1,field2...) doc(field1,field2...) \ indexer /
_____________ | Lucene Index| -------------- / searcher \
l果输出QHits(doc(field1,field2) doc(field1...))
索引数据源:record(field1,field2...) record(field1..) \ SQL: insert/
_____________ | DB Index | ------------- / SQL: select
\l果输出Qresults(record(field1,field2..) record(field1...))
DocumentQ一个需要进行烦引的“单元”
一个Document由多个字D늻?RecordQ记录,包含多个字段
FieldQ字D?FieldQ字D?
HitsQ查询结果集Q由匚w的Documentl成 RecordSetQ查询结果集Q由多个Recordl成
全文?≠ like "%keyword%"
通常比较厚的书籍后面常常附关键词索引表(比如Q北京:12,
34,上vQ?,77?#8230;…Q,它能够帮助读者比较快地找到相兛_容的늠。而数据库索引能够大大提高查询的速度原理也是一P惛_一下通过书后面的?
引查扄速度要比一一地d定w多少?#8230;…而烦引之所以效率高Q另外一个原因是它是排好序的。对于检索系l来说核心是一个排序问题?br />
׃数据库烦引不是ؓ全文索引设计的,因此Q用like
"%keyword%"Ӟ数据库烦引是不v作用的,在用like查询Ӟ搜烦q程又变成类g一页M的遍历过E了Q所以对于含有模p查询的数据?
服务来说QLIKEҎ(gu)能的危x极大的。如果是需要对多个关键词进行模p匹配:like"%keyword1%" and like
"%keyword2%" ...其效率也可惌知了?br />
所以徏立一个高效检索系l的关键是徏立一个类gU技索引一L反向索引机制Q将数据源(比如多篇文章Q排序顺序存储的同时Q有另外一个排好序的关键词?
表,用于存储关键?=>文章映射关系Q利用这L映射关系索引Q[关键?=>出现关键词的文章~号Q出现次敎ͼ甚至包括位置Qv始偏U?
量,l束偏移量)Q出现频率]Q检索过E就是把模糊查询变成多个可以利用索引的精查询的逻辑l合的过E。从而大大提高了多关键词查询的效率,所以,全文
索问题归l到最后是一个排序问题?br />
由此可以看出模糊查询相对数据库的_查询是一个非怸定的问题,q也是大部分数据库对全文索支持有限的原因。Lucene最核心的特征是通过Ҏ(gu)?
索引l构实现了传l数据库不擅长的全文索引机制Qƈ提供了扩展接口,以方侉K对不同应用的定制?br />
可以通过一下表格对比一下数据库的模p查询:
Lucene全文索引引擎 数据?
索引 数据源中的数据都通过全文索引一一建立反向索引 对于LIKE查询来说Q数据传l的索引是根本用不上的。数据需要逐个便利记录q行GREP式的模糊匚wQ比有烦引的搜烦速度要有多个数量U的下降?
匚w效果 通过词元(term)q行匚wQ通过语言分析接口的实玎ͼ可以实现对中文等非英语的支持?使用Qlike "%net%" 会把netherlands也匹配出来,
多个关键词的模糊匚wQ用like "%com%net%"Q就不能匚w词序颠倒的xxx.net..xxx.com
匚w?有匹配度法Q将匚wE度Q相似度Q比较高的结果排在前面?没有匚wE度的控Ӟ比如有记录中net出现5词和出现1ơ的Q结果是一L?
l果输出 通过特别的算法,最匚w度最高的?00条结果输出,l果集是~冲式的批量读取的?q回所有的l果集,在匹配条目非常多的时候(比如上万条)需要大量的内存存放q些临时l果集?
可定制?通过不同的语a分析接口实现Q可以方便的定制出符合应用需要的索引规则Q包括对中文的支持) 没有接口或接口复杂,无法定制
l论 高负载的模糊查询应用Q需要负责的模糊查询的规则,索引的资料量比较?使用率低Q模p匹配规则简单或者需要模p查询的资料量少
全文索和数据库应用最大的不同在于Q让最相关的头100条结果满?8%以上用户的需?br />
Lucene的创C处:
大部分的搜烦Q数据库Q引擎都是用B树结构来l护索引Q烦引的更新会导致大量的IO操作QLucene在实CQ对此稍微有所改进Q不是维护一个烦引文
Ӟ而是在扩展烦引的时候不断创建新的烦引文Ӟ然后定期的把q些新的烦引文件合q到原先的大索引中(针对不同的更新策略,Ҏ(gu)的大可以调_Q这?
在不影响索的效率的前提下Q提高了索引的效率?br />
Lucene和其他一些全文检索系l?应用的比较:
Lucene 其他开源全文检索系l?
增量索引和批量烦?可以q行增量的烦?Append)Q可以对于大量数据进行批量烦引,q且接口设计用于优化扚w索引和小扚w的增量烦引?很多pȝ只支持批量的索引Q有时数据源有一点增加也需要重建烦引?
数据?Lucene没有定义具体的数据源Q而是一个文档的l构Q因此可以非常灵zȝ适应各种应用Q只要前端有合适的转换器把数据源{换成相应l构Q, 很多pȝ只针对网,~Z其他格式文档的灵zL?
索引内容抓取 Lucene的文档是由多个字D늻成的Q甚臛_以控刉些字D需要进行烦引,那些字段不需要烦引,q一步烦引的字段也分为需要分词和不需要分词的cdQ?br />
需要进行分词的索引Q比如:标题Q文章内容字D?br />
不需要进行分词的索引Q比如:作?日期字段 ~Z通用性,往往文档整个烦引了
语言分析 通过语言分析器的不同扩展实现Q?br />
可以qo掉不需要的词:an the of {,
西文语法分析Q将jumps jumped jumper都归l成jumpq行索引/?br />
非英文支持:对亚z语aQ阿拉伯语言的烦引支?~Z通用接口实现
查询分析 通过查询分析接口的实玎ͼ可以定制自己的查询语法规则:
比如Q?多个关键词之间的 + - and or关系{?
q发讉K 能够支持多用L使用
关于亚洲语言的的切分词问?Word Segment)
对于中文来说Q全文烦引首先还要解决一个语a分析的问题,对于英文来说Q语句中单词之间是天焉过I格分开的,但亚z语a的中日韩文语句中的字是一个字挨一个,所有,首先要把语句中按“?#8221;q行索引的话Q这个词如何切分出来是一个很大的问题?br />
首先Q肯定不能用单个字符?si-gram)为烦引单元,否则?#8220;上v”Ӟ不能让含?#8220;上”也匹配?br />
但一句话Q?#8220;北京天安?#8221;Q计机如何按照中文的语a习惯q行切分呢?
“北京 天安?#8221; q是“??天安?#8221;Q让计算够按照语a习惯q行切分Q往往需要机器有一个比较丰富的词库才能够比较准的识别句中的单词?br />
另外一个解决的办法是采用自动切分算法:单词按?元语?bigram)方式切分出来Q比如:
"北京天安? ==> "北京 京天 天安 安门"?br />
q样Q在查询的时候,无论是查?北京"
q是查询"天安?Q将查询词组按同L规则q行切分Q?北京"Q?天安安门"Q多个关键词之间按与"and"的关pȝ合,同样能够正确地映到相应的烦
引中。这U方式对于其他亚z语aQ韩文,日文都是通用的?br />
Z自动切分的最大优Ҏ(gu)没有词表l护成本Q实现简单,~点是烦引效率低Q但对于中小型应用来_Z2元语法的切分q是够用的。基?元切分后的烦引一般大和源文件差不多Q而对于英文,索引文g一般只有原文g?0%-40%不同Q?br />
自动切分 词表切分
实现 实现非常?实现复杂
查询 增加了查询分析的复杂E度Q?适于实现比较复杂的查询语法规?
存储效率 索引冗余大,索引几乎和原文一样大 索引效率高,为原文大的30Q左?
l护成本 无词表维护成?词表l护成本非常高:中日韩等语言需要分别维护?br />
q需要包括词频统计等内容
适用领域 嵌入式系l:q行环境资源有限
分布式系l:无词表同步问?br />
多语a环境Q无词表l护成本 Ҏ(gu)询和存储效率要求高的专业搜烦引擎
目前比较大的搜烦引擎的语a分析法一般是Z以上2个机制的l合。关于中文的语言分析法Q大家可以在Google查关键词"wordsegment search"能找到更多相关的资料?br />
安装和?br />
下蝲Qhttp://jakarta.apache.org/lucene/
注意QLucene中的一些比较复杂的词法分析是用JavaCC生成的(JavaCCQJavaCompilerCompilerQ纯Java的词法分?
生成器)Q所以如果从源代码编译或需要修改其中的QueryParser、定制自q词法分析器,q需要从
https://javacc.dev.java.net/下蝲javacc?br />
lucene的组成结构:对于外部应用来说索引模块(index)和检索模?search)是主要的外部应用入口
org.apache.Lucene.search/ 搜烦入口
org.apache.Lucene.index/ 索引入口
org.apache.Lucene.analysis/ 语言分析?
org.apache.Lucene.queryParser/ 查询分析?
org.apache.Lucene.document/ 存储l构
org.apache.Lucene.store/ 底层IO/存储l构
org.apache.Lucene.util/ 一些公用的数据l构
单的例子演示一下Lucene的用方法:
索引q程Q从命o行读取文件名Q多个)Q将文g分\?path字段)和内?body字段)2个字D进行存储,q对内容q行全文索引Q烦引的单位?
Document对象Q每个Document对象包含多个字段Field对象Q针对不同的字段属性和数据输出的需求,对字D还可以选择不同的烦?存储?
D规则,列表如下Q?Ҏ(gu) 切词 索引 存储 用?
Field.Text(String name, String value) Yes Yes Yes 切分词烦引ƈ存储Q比如:标题Q内容字D?
Field.Text(String name, Reader value) Yes Yes No 切分词烦引不存储Q比如:META信息Q?br />
不用于返回显C,但需要进行检索内?
Field.Keyword(String name, String value) No Yes Yes 不切分烦引ƈ存储Q比如:日期字段
Field.UnIndexed(String name, String value) No No Yes 不烦引,只存储,比如Q文件\?
Field.UnStored(String name, String value) Yes Yes No 只全文烦引,不存?
public class IndexFiles { //使用Ҏ(gu)Q? IndexFiles [索引输出目录] [索引的文件列表] ...
public static void main(String[] args) throws Exception { String
indexPath = args[0]; IndexWriter writer;
//用指定的语言分析器构造一个新的写索引器(W?个参数表C是否ؓq加索引Q?writer = new
IndexWriter(indexPath, new SimpleAnalyzer(), false); for (int i=1;
i<args.length; i++) { System.out.println("Indexing file " + args); InputStream is = new FileInputStream(args);
//构造包?个字DField的Document对象 //一个是路径path字段Q不索引Q只存储
//一个是内容body字段Q进行全文烦引,q存?Document doc = new Document();
doc.add(Field.UnIndexed("path", args)); doc.add(Field.Text("body",
(Reader) new InputStreamReader(is))); //文档写入烦?
writer.addDocument(doc); is.close(); }; //关闭写烦引器 writer.close();
}} 索引q程中可以看刎ͼ
语言分析器提供了抽象的接口,因此语言分析(Analyser)是可以定制的Q虽然lucene~省提供?个比较通用的分析器
SimpleAnalyser和StandardAnalyserQ这2个分析器~省都不支持中文Q所以要加入对中文语a的切分规则,需要修改这2个分?
器?
Luceneq没有规定数据源的格式,而只提供了一个通用的结构(Document对象Q来接受索引的输入,因此输入的数据源可以是:数据库,WORD?
档,PDF文档QHTML文档……只要能够设计相应的解析{换器数据源构造成成Docuement对象卛_q行索引?
对于大批量的数据索引Q还可以通过调整IndexerWrite的文件合q率属性(mergeFactorQ来提高扚w索引的效率?
索过E和l果昄Q?br />
搜烦l果q回的是Hits对象Q可以通过它再讉KDocument==>Field中的内容?br />
假设Ҏ(gu)body字段q行全文索,可以查询结果的path字段和相应查询的匚w?score)打印出来Q?br />
public class Search { public static void main(String[] args) throws
Exception { String indexPath = args[0], queryString = args[1];
//指向索引目录的搜索器 Searcher searcher = new IndexSearcher(indexPath);
//查询解析器:使用和烦引同L语言分析?Query query = QueryParser.parse(queryString,
"body", new SimpleAnalyzer()); //搜烦l果使用Hits存储 Hits hits =
searcher.search(query); //通过hits可以讉K到相应字D늚数据和查询的匚w?for (int i=0;
i<hits.length(); i++) { System.out.println(hits.doc(i).get("path") +
"; Score: " + hits.score(i)); };
}}在整个检索过E中Q语a分析器,查询分析器,甚至搜烦器(SearcherQ都是提供了抽象的接口,可以Ҏ(gu)需要进行定制?
Hacking Lucene
化的查询分析?br />
个h感觉lucene成ؓJAKARTA目后,d了太多的旉用于调试日趋复杂QueryParserQ而其中大部分是大多数用户q不很熟(zhn)的Q目前LUCENE支持的语法:
Query ::= ( Clause )*
Clause ::= ["+", "-"] [<TERM> ":"] ( <TERM> | "(" Query ")")
中间的逻辑包括Qand or + -
&&||{符P而且q有"短语查询"和针对西文的前缀/模糊查询{,个h感觉对于一般应用来_q些功能有一些华而不实,其实能够实现
目前cM于Google的查询语句分析功能其实对于大多数用户来说已经够了。所以,Lucene早期版本的QueryParser仍是比较好的选择?br />
d修改删除指定记录QDocumentQ?br />
Lucene提供了烦引的扩展机制Q因此烦引的动态扩展应该是没有问题的,而指定记录的修改也似乎只能通过记录的删除,然后重新加入实现。如何删除指定的
记录呢?删除的方法也很简单,只是需要在索引时根据数据源中的记录ID专门另徏索引Q然后利用IndexReader.delete(Termterm)
Ҏ(gu)通过q个记录ID删除相应的Document?br />
Ҏ(gu)某个字段值的排序功能
lucene~省是按照自q相关度算法(scoreQ进行结果排序的Q但能够Ҏ(gu)其他字段q行l果排序是一个在LUCENE的开发邮件列表中l常提到?
问题Q很多原先基于数据库应用都需要除了基于匹配度QscoreQ以外的排序功能。而从全文索的原理我们可以了解刎ͼM不基于烦引的搜烦q程效率都会
D效率非常的低Q如果基于其他字D늚排序需要在搜烦q程中访问存储字D,速度回大大降低,因此非常是不可取的?br />
但这里也有一个折中的解决Ҏ(gu)Q在搜烦q程中能够媄响排序结果的只有索引中已l存储的docID和scoreq?个参敎ͼ所以,Zscore以外的排
序,其实可以通过数据源预先排好序,然后Ҏ(gu)docIDq行排序来实现。这样就避免了在LUCENE搜烦l果外对l果再次q行排序和在搜烦q程中访问不
在烦引中的某个字D倹{?br />
q里需要修改的是IndexSearcher中的HitCollectorq程Q?br />
... scorer.score(new HitCollector() { private float minScore = 0.0f;
public final void collect(int doc, float score) { if (score > 0.0f
&& // ignore zeroed buckets (bits==null || bits.get(doc))) { //
skip docs not in bits totalHits[0]++; if (score >= minScore) { /*
原先QLucenedocID和相应的匚w度score例入l果命中列表中: * hq.put(new ScoreDoc(doc,
score)); // update hit queue * 如果用doc ?1/doc 代替 scoreQ就实现了根据docID排或逆排
* 假设数据源烦引时已经按照某个字段排好了序Q而结果根据docID排序也就实现?*
针对某个字段的排序,甚至可以实现更复杂的score和docID的拟合?*/ hq.put(new ScoreDoc(doc, (float)
1/doc )); if (hq.size() > nDocs) { // if hit queue overfull
hq.pop(); // remove lowest in hit queue minScore =
((ScoreDoc)hq.top()).score; // reset minScore } } } } },
reader.maxDoc());
3, 计算匚w得分. 于1.0的我们认为是相关的记录了.下面的代码在输出l果循环? 如果要获取完全匹配的记录,
//计算匚w得分
Explanation explanation = searcher.explain(query, hits.id(i)) ;
System.out.println("匚w得分:"+explanation.getValue());
System.out.println("=========");
4, 关于短语匚w的用?br />
通过短语搜烦QPhraseQuery
索引中包含了各个的位置信息。PhraseQuery利用q些信息L索文档,在这些文档集中,我们所查找的各个项之间可能都相隔着一定的距离。例如,
假设某个域中包含?#8220;the quick brown fox jumped over the lazy
dog”q个短语Q即使我们不知道q个短语的确切完整写法,也一样可以通过查找域中quick和fox距离相近的文档来扑և我们需要的文档。当Ӟ一个简
单的TermQuery也能够通过对这两个的单独查询成功地找到同h档;但是在以上所讨论的情况中Q我们仅仅希望查到域中quick的位|紧挨着
fox或者隔一个不相关的单词的文档Q如quick [不相关的词] foxQ?br />
在匹配的情况下,两个的位置之间允许的最大间隔距ȝ为slop。距L指项要按序l成l定的短语,所需要移动位|的ơ数。我们用刚刚提到的那个短
语,看看slop因子是怎么样工作的。首先,我们需要构Z个小的基本测试构ӞE序里用一个setUp()Ҏ(gu)来烦引一个文档,q过
matched(String[], int)Ҏ(gu)构造、执行ƈ断言一个短语查询与我们的测试文档相匚wQ?br />
// 建立h文档
׃只想C一下几个短语查询的例子Q因此在以上E序中我们简化了matchedҎ(gu)的代码。这个程序按照一定的序d各个Ҏ(gu)q行短语查询。默认情?
下,PhraseQuery的slop因子讄?Q即要求查询的结果必d我们输入的字W串l完全精一致地匚w。通过setUp()?
matched()Ҏ(gu)Q测试用例对PhraseQuery的工作方式做Zz的C。程序以查询p|或超出slop因子作ؓ其边界:
?.2 解释短语查询slop因子Q短?#8220;quick fox”需要slopgؓ1的移动才能和原文档匹配,?#8220;fox quick”需要slopgؓ3的移动才能匹?br />
在短语查询中Q虽焉出现的先后顺序会对slop因子的选取有一定媄响,但是我们不一定需要按照这些项在文档中出现的先后顺序来它们添加至
PhraseQuery中。例如,如果把上qString数组中的两个w倒(先是?#8220;fox”Q然后是“quick”Q,要和文档匚w需要移动三个位
|,而不是原先的一个了。ؓ了表辑־更Ş象一些,可以思考一下单?#8220;fox”需要移动多个位置才能位于单词“quick”的两个位|之后。你会发?
foxUd一ơ到达quick的位|,然后再移动两ơ才能之变?#8220;quick X fox”Q从而和“quick brown fox”充分地匹配?br />
?.2展示了slop位置因子在这两个短语查询场景的应用是如何工作的,下面的测试用例示范了E序如何通过slop因子的设|实现对String[] {"fox", "quick"}的匹配:
现在我们开始深入学习如何对多个进行复合查询的问题?br />
复合短?br />
PhraseQuery支持复合短语(multiple-term phrasesQ。不短语中有多个,slop因子都规定了Ҏ(gu)序Ud位置的所允许的最大倹{下面看看关于复合项短语查询的一个示例:
到目前ؓ止,你已l了解了短语查询是如何进行匹配的Q下面我们把注意力{向于短语查询Ҏ(gu)档评分的影响?br />
短语查询评分
短语查询是根据短语匹配所需要的~辑距离来进行评分的。项之间距离小的匹配具有的权重也就大。短语查询的评分因子如图3.3所C。评分与距离成反比关p,距离大的匹配其评分低?br />
?.3 短语查询的评分公?br />
注:在QueryParser的分析表辑ּ中双引号里的若干个项被被转换Z个PhraseQuery对象。Slop因子的默认值是0Q但是你可以?
QueryParser的查询表辑ּ中加上~n的声明,以此来调整slop因子的倹{例如,表达?#8220;quick
fox”~3的意义ؓQؓfox和quick生成一个slop因子?的PhraseQuery对象。更多关于PhraseQuery和slop因子?
l节请参?.5.6节。短语由传给QueryParser的分析器q行分析Q在此过E中q会加入另外一个复杂的层,q个内容会?.1.2节中加
以讨论?/em>
]]> [转]lucene学习W记?- 关于l果分页 http://www.aygfsteel.com/super2/archive/2008/10/29/237305.html淘声依旧 淘声依旧 Wed, 29 Oct 2008 02:04:00 GMT http://www.aygfsteel.com/super2/archive/2008/10/29/237305.html http://www.aygfsteel.com/super2/comments/237305.html http://www.aygfsteel.com/super2/archive/2008/10/29/237305.html#Feedback 0 http://www.aygfsteel.com/super2/comments/commentRss/237305.html http://www.aygfsteel.com/super2/services/trackbacks/237305.html 一 ,Hits对象是搜索结果的集合 主要有下面几个方?[list=1]
length() ,q个Ҏ(gu)记录有多条l果q回(lazy loading)
doc(n) q回Wn个记?/li>
id(in) q回Wn个记录的Document ID
score(n) Wn个记录的相关?U分)
׃搜烦的结果一般比较大Q从性能上考虑QHits对象q不会真正把所有的l果全部取回Q默认情况下是保留前100个记?对于一般的搜烦引擎,100个记录够了).
分页的处?/strong>
100条记录还是太多,我们多半会每|C?0条记录,然后分ؓ若干|C,对于分页Q一般有两个办法
[list=1]
在session中保留indexreader对象和hit对象Q翻늚时候提取内?/li>
不用sessionQ每ơ都单处理ؓ重新查询
lucene推荐先用第二个办法Q即每次都重新查询,q样做的好处是简单方便,不需要考虑session的问题,lucene的查询效率也能保证每ơ查询时间不长,除非真正有了性能问题Q否则不用考虑W一个办法?br />
Lucene面向全文索的优化在于首次索引索后Qƈ不把所有的记录QDocumentQ具体内容读取出来,而v只将所有结果中匚w度最高的?00?
l果QTopDocsQ的ID攑ֈl果集缓存中q返回,q里可以比较一下数据库索:如果是一?0,000条的数据库检索结果集Q数据库是一定要把所?
记录内容都取得以后再开始返回给应用l果集的。所以即使检索匹配L很多QLucene的结果集占用的内存空间也不会很多。对于一般的模糊索应用是用不
到这么多的结果的Q头100条已l可以满?0%以上的检索需求?br />
如果首批~存l果数用完后q要d更后面的l果时Searcher会再ơ检索ƈ生成一个上ơ的搜烦~存数大1倍的~存Qƈ再重新向后抓取。所以如果构造一
个SearcherL1Q?20条结果,Searcher其实是进行了2ơ搜索过E:?00条取完后Q缓存结果用完,Searcher重新索再构?
一?00条的l果~存Q依此类推,400条缓存,800条缓存。由于每ơSearcher对象消失后,q些~存也访问那不到了,你有可能惛_l果记录~?
存下来,~存数尽量保证在100以下以充分利用首ơ的l果~存Q不让Lucene费多次索,而且可以分q行l果~存?br />
Lucene的另外一个特Ҏ(gu)在收集结果的q程中将匚w度低的结果自动过滤掉了。这也是和数据库应用需要将搜烦的结果全部返回不同之处?br />
我的一些尝?/font> Q?/li>
]]>[转]lucene学习W记?分词 http://www.aygfsteel.com/super2/archive/2008/10/29/237303.html淘声依旧 淘声依旧 Wed, 29 Oct 2008 02:03:00 GMT http://www.aygfsteel.com/super2/archive/2008/10/29/237303.html http://www.aygfsteel.com/super2/comments/237303.html http://www.aygfsteel.com/super2/archive/2008/10/29/237303.html#Feedback 0 http://www.aygfsteel.com/super2/comments/commentRss/237303.html http://www.aygfsteel.com/super2/services/trackbacks/237303.html
注意QLucene中的一些比较复杂的词法分析是用JavaCC生成的(JavaCCQJavaCompilerCompilerQ纯Java的词?
分析生成器)Q所以如果从源代码编译或需要修改其中的QueryParser、定制自q词法分析器,q需要从https://javacc.dev.java.net/ 下蝲javacc?
lucene的组成结构:对于外部应用来说索引模块(index)和检索模?search)是主要的外部应用入口?org.apache.Lucene.search/ 搜烦入口
org.apache.Lucene.index/ 索引入口
org.apache.Lucene.analysis/ 语言分析?
org.apache.Lucene.queryParser/ 查询分析?
org.apache.Lucene.document/ 存储l构
org.apache.Lucene.store/ 底层IO/存储l构
org.apache.Lucene.util/ 一些公用的数据l构
2, 关于计划于词库的分词和一元分?二元分词的区? noise.chs 是词库中作ؓstopword而存在的.请大家注?
下面做了详细描述:
2006q?1?2?星期??2:39 am · 发表? 默认
Lucene应用来多Q在对中文对索引q程中,中文分词问题也就来重要?
在已有的分词模式中,目前比较常用的也是比较通用的有一元分词、二元分词和Z词库的分词三U。一元分词在Java版本上由yysun实现Qƈ且已l收?
到Apache。其实现方式比较单,卛_每一个汉字作Z个TokenQ例如:“q是中文?#8221;Q在l过一元分词模式分词后的结果ؓ五个TokenQ这?
是、中、文、字。而二元分词,则将两个相连的汉字作Z个Token划分Q例如:“q是中文?#8221;Q运用二元分词模式分词后Q得到的l果为:q是、是中、中
文、文字?
一元分词和二元分词实现原理比较单,基本支持所有东方语a。但二者的~陷也比较明显。一元分词单U的考虑了中文的文字而没有考虑C文的词性,例如在上
q的例子中,“中文”?#8220;文字”q两个十分明昄中文词语没有被识别出来。相反,二元分词则分Z太多的冗余的中文词,如上所qͼ“q是”?#8220;是中”?
无意义的文字l合竟被划分Z个词语,而同L~陷Q命中的词语也不十分准确Q如上:?#8220;q是中文?#8221;中,“中文?#8221;q个词语应该优先考虑的。而二元分?
也未能实现?
Z词库的分词实现难度比较大Q其模式也有多种Q如微Y在自q软g中的汉语分词、v量的中文分词研究版,q有目前?Net下实现的使用率较高的猎兔Q?
和一些其他h自发实现的分词工L{。其都有自己的分析体p,虽然分析_ֺ高,但实现难度大Q实现周期长Q而且Q对一般的中小型应用系l来Ԍ在精度的?
求不是十分苛ȝ环境下,q种模式对系l对消耗是一U奢侈行为?
在综合考虑一元分词、二元分词及Z词库的分词模式后Q我大胆提出一U基于StopWord分割的分词模式。这U分词模式的设计思想是,针对要分割的D?
落,先由标点分割成标准的短句。然后根据设定的StopWordQ将短句由StopWord最大化分割Q分割ؓ一个个词语。如Q输入短句ؓ“q是中文?
”Q设定的StopWord列表为:“q?#8221;?#8220;?#8221;Q则最l的l果为:“中文?#8221;?
q个例子相对比较单,举个E微长一点的例子Q输入短?#8220;中文软g需要具有对中文文本的输入、显C、编辑、输出等基本功能”Q设定的StopWord列表为:“q?#8221;?#8220;?#8221;?#8220;?#8221;?#8220;?#8221;?#8220;{?#8221;?#8220;需?#8221;?#8220;h”Q则分割出对l果列表为:
====================
中文软g
中文文本
输入
昄
~辑
输出
基本功能
====================
基本实现了想要的l果Q但其中也不乏不之处,如上q的l果?#8220;中文软g”?#8220;中文文本”应该分割Z个独立词“中文”?#8220;软g”?#8220;文本”Q而不是上q的l果?
q且Q对StopWord列表对设|,也是相对比较复杂的环节,没有一个确定的U束来设定StopWord。我的想法是Q可以将一些无意义的主语,?#8220;?
”?#8220;?#8221;?#8220;?#8221;?#8220;我们”?#8220;他们”{,动词“?#8221;?#8220;?#8221;?#8220;?#8221;{等其他各种词性诸?#8220;?#8221;?#8220;?#8221;?#8220;一”?#8220;?#8221;?#8220;?#8221;?#8220;?#8221;{等
QSystem32目录下noise.chs文g里的内容可以作ؓ参考)作ؓStopWord?
noise.chs 是词库中作ؓstopword而存在的.请大家注?
3, 关于分词?q可以关注这个帖?
http://lucene-group.group.javaeye.com/group/blog/58701
自己写的一个基于词库的lucene分词E序--ThesaurusAnalyzer
我已l测试过.q可?18万分?
4, lucene的自带分词的试如下:\
Lucene本n提供了几个分词接?我后来有l写了一个分词接?
功能递增如下:
WhitespaceAnalyzer:仅仅是去除空|对字W没有lowcase?不支持中?
SimpleAnalyzer:功能ZWhitespaceAnalyzer,除去letter之外的符号全部过滤掉,q且所有的字符lowcase?不支持中?
StopAnalyzer:StopAnalyzer的功能超了SimpleAnalyzerQ在SimpleAnalyzer的基?
增加了去除StopWords的功?不支持中?
StandardAnalyzer:英文的处理能力同于StopAnalyzer.支持中文采用的方法ؓ单字切分.
ChineseAnalyzer:来自于Lucene的sand box.性能cM于StandardAnalyzer,~点是不支持中英文和分?
CJKAnalyzer:chedong写的CJKAnalyzer的功能在英文处理上的功能和StandardAnalyzer相同
但是在汉语的分词上,不能qo掉标点符P即用二元切?
TjuChineseAnalyzer:我写?功能最为强?TjuChineseAnlyzer的功能相当强?在中文分词方面由于其调用的ؓ
ICTCLAS的java接口.所以其在中文方面性能上同与ICTCLAS.其在英文分词上采用了Lucene的StopAnalyzer,可以去除
stopWords,而且可以不区分大写,qo掉各cL点符?
E序调试?JBuilder 2005
package org.apache.lucene.analysis;
//Author:zhangbufeng
//TjuAILab(天|大学人工实验?
//2005.9.22.11:00
import java.io.*;
import junit.framework.*;
import org.apache.lucene.*;
import org.apache.lucene.analysis.*;
import org.apache.lucene.analysis.StopAnalyzer;
import org.apache.lucene.analysis.standard.*;
import org.apache.lucene.analysis.cn.*;
import org.apache.lucene.analysis.cjk.*;
import org.apache.lucene.analysis.tjucn.*;
import com.xjt.nlp.word.*;
public class TestAnalyzers extends TestCase {
public TestAnalyzers(String name) {
super(name);
}
public void assertAnalyzesTo(Analyzer a,
String input,
String[] output) throws Exception {
//前面?dummy"好像没有用到
TokenStream ts = a.tokenStream("dummy", new StringReader(input));
StringReader readerInput=new StringReader(input);
for (int i=0; i Token t = ts.next();
//System.out.println(t);
assertNotNull(t);
//使用下面q条语句卛_以输出Token的每的text,q且用空格分开
System.out.print(t.termText);
System.out.print(" ");
assertEquals(t.termText(), output);
}
System.out.println(" ");
assertNull(ts.next());
ts.close();
}
public void outputAnalyzer(Analyzer a ,String input) throws Exception{
TokenStream ts = a.tokenStream("dummy",new StringReader(input));
StringReader readerInput = new StringReader(input);
while(true){
Token t = ts.next();
if(t!=null){
System.out.print(t.termText);
System.out.print(" ");
}
else
break;
}
System.out.println(" ");
ts.close();
}
public void testSimpleAnalyzer() throws Exception {
//学习使用SimpleAnalyzer();
//SimpleAnalyzer除去letter之外的符号全部过滤掉,q且所有的字符lowcase?
Analyzer a = new SimpleAnalyzer();
assertAnalyzesTo(a, "foo bar FOO BAR",
new String[] { "foo", "bar", "foo", "bar" });
assertAnalyzesTo(a, "foo bar . FOO <> BAR",
new String[] { "foo", "bar", "foo", "bar" });
assertAnalyzesTo(a, "foo.bar.FOO.BAR",
new String[] { "foo", "bar", "foo", "bar" });
assertAnalyzesTo(a, "U.S.A.",
new String[] { "u", "s", "a" });
assertAnalyzesTo(a, "C++",
new String[] { "c" });
assertAnalyzesTo(a, "B2B",
new String[] { "b", "b" });
assertAnalyzesTo(a, "2B",
new String[] { "b" });
assertAnalyzesTo(a, "\"QUOTED\" word",
new String[] { "quoted", "word" });
assertAnalyzesTo(a,"zhang ./ bu <> feng",
new String[]{"zhang","bu","feng"});
ICTCLAS splitWord = new ICTCLAS();
String result = splitWord.paragraphProcess("我爱大家 i LOVE chanchan");
assertAnalyzesTo(a,result,
new String[]{"?,"?,"大家","i","love","chanchan"});
}
public void testWhiteSpaceAnalyzer() throws Exception {
//WhiterspaceAnalyzer仅仅是去除空|对字W没有lowcase?
Analyzer a = new WhitespaceAnalyzer();
assertAnalyzesTo(a, "foo bar FOO BAR",
new String[] { "foo", "bar", "FOO", "BAR" });
assertAnalyzesTo(a, "foo bar . FOO <> BAR",
new String[] { "foo", "bar", ".", "FOO", "<>", "BAR" });
assertAnalyzesTo(a, "foo.bar.FOO.BAR",
new String[] { "foo.bar.FOO.BAR" });
assertAnalyzesTo(a, "U.S.A.",
new String[] { "U.S.A." });
assertAnalyzesTo(a, "C++",
new String[] { "C++" });
assertAnalyzesTo(a, "B2B",
new String[] { "B2B" });
assertAnalyzesTo(a, "2B",
new String[] { "2B" });
assertAnalyzesTo(a, "\"QUOTED\" word",
new String[] { "\"QUOTED\"", "word" });
assertAnalyzesTo(a,"zhang bu feng",
new String []{"zhang","bu","feng"});
ICTCLAS splitWord = new ICTCLAS();
String result = splitWord.paragraphProcess("我爱大家 i love chanchan");
assertAnalyzesTo(a,result,
new String[]{"?,"?," 大家 ","i","love","chanchan"});
}
public void testStopAnalyzer() throws Exception {
//StopAnalyzer的功能超了SimpleAnalyzerQ在SimpleAnalyzer的基?
//增加了去除StopWords的功?
Analyzer a = new StopAnalyzer();
assertAnalyzesTo(a, "foo bar FOO BAR",
new String[] { "foo", "bar", "foo", "bar" });
assertAnalyzesTo(a, "foo a bar such FOO THESE BAR",
new String[] { "foo", "bar", "foo", "bar" });
assertAnalyzesTo(a,"foo ./ a bar such ,./<> FOO THESE BAR ",
new String[]{"foo","bar","foo","bar"});
ICTCLAS splitWord = new ICTCLAS();
String result = splitWord.paragraphProcess("我爱 大家 i Love chanchan such");
assertAnalyzesTo(a,result,
new String[]{"?,"?," 大家 ","i","love","chanchan"});
}
public void testStandardAnalyzer() throws Exception{
//StandardAnalyzer的功能最为强大,对于中文采用的ؓ单字切分
Analyzer a = new StandardAnalyzer();
assertAnalyzesTo(a,"foo bar Foo Bar",
new String[]{"foo","bar","foo","bar"});
assertAnalyzesTo(a,"foo bar ./ Foo ./ BAR",
new String[]{"foo","bar","foo","bar"});
assertAnalyzesTo(a,"foo ./ a bar such ,./<> FOO THESE BAR ",
new String[]{"foo","bar","foo","bar"});
assertAnalyzesTo(a,"张步峰是天大学生",
new String[]{"?,"?,"?,"?,"?,"?,"?,"?});
//验证去除英文的标点符?
assertAnalyzesTo(a,"?/?,?.?,天大<>学生",
new String[]{"?,"?,"?,"?,"?,"?,"?,"?});
//验证去除中文的标点符?
assertAnalyzesTo(a,"张。、步。、峰是。天大。学?,
new String[]{"?,"?,"?,"?,"?,"?,"?,"?});
}
public void testChineseAnalyzer() throws Exception{
//可见ChineseAnalyzer在功能上和standardAnalyzer的功能差不多Q但是可能在速度上慢于StandardAnalyzer
Analyzer a = new ChineseAnalyzer();
//ȝ?
assertAnalyzesTo(a,"foo bar Foo Bar",
new String[]{"foo","bar","foo","bar"});
assertAnalyzesTo(a,"foo bar ./ Foo ./ BAR",
new String[]{"foo","bar","foo","bar"});
assertAnalyzesTo(a,"foo ./ a bar such ,./<> FOO THESE BAR ",
new String[]{"foo","bar","foo","bar"});
assertAnalyzesTo(a,"张步峰是天大学生",
new String[]{"?,"?,"?,"?,"?,"?,"?,"?});
//验证去除英文的标点符?
assertAnalyzesTo(a,"?/?,?.?,天大<>学生",
new String[]{"?,"?,"?,"?,"?,"?,"?,"?});
//验证去除中文的标点符?
assertAnalyzesTo(a,"张。、步。、峰是。天大。学?,
new String[]{"?,"?,"?,"?,"?,"?,"?,"?});
//不支持中英文写在一?
// assertAnalyzesTo(a,"我爱?i love chanchan",
/// new String[]{"?,"?,"?,"i","love","chanchan"});
}
public void testCJKAnalyzer() throws Exception {
//chedong写的CJKAnalyzer的功能在英文处理上的功能和StandardAnalyzer相同
//但是在汉语的分词上,不能qo掉标点符P即用二元切?
Analyzer a = new CJKAnalyzer();
assertAnalyzesTo(a,"foo bar Foo Bar",
new String[]{"foo","bar","foo","bar"});
assertAnalyzesTo(a,"foo bar ./ Foo ./ BAR",
new String[]{"foo","bar","foo","bar"});
assertAnalyzesTo(a,"foo ./ a bar such ,./<> FOO THESE BAR ",
new String[]{"foo","bar","foo","bar"});
// assertAnalyzesTo(a,"?/?,?.?,天大<>学生",
// new String[]{"张步","步峰","峰是","是天","天大","大学","学生"});
//assertAnalyzesTo(a,"张。、步。、峰是。天大。学?,
// new String[]{"张步","步峰","峰是","是天","天大","大学","学生"});
//支持中英文同时写
assertAnalyzesTo(a,"张步峰是天大学生 i love",
new String[]{"张步","步峰","峰是","是天","天大","大学","学生","i","love"});
}
public void testTjuChineseAnalyzer() throws Exception{
/**
* TjuChineseAnlyzer的功能相当强?在中文分词方面由于其调用的ؓICTCLAS的java接口.
* 所以其在中文方面性能上同与ICTCLAS.其在英文分词上采用了Lucene的StopAnalyzer,可以去除
* stopWords,而且可以不区分大写,qo掉各cL点符?
*/
Analyzer a = new TjuChineseAnalyzer();
String input = "体育讯 在被文淘汰之后Q皇马主帅博斯克拒绝接受媒体对球队后防线的批评,同时qؓ自己排出的首发阵容进行了辩护?+
"“失利是全队的责QQ而不仅仅是后防线该受指责Q?#8221;博斯克说Q?#8220;我ƈ不认为我们踢得一塌糊涂?#8221;“我们q入了半册Q而且在晋U的道\上一路奋 "+
"战。即使是今天的比赛我们也有几个翻w的ZQ但我们面对的对手非常强大,他们t得非常好?#8221;“我们的球q应该ؓq去几个赛季里我们在冠军杯中的表现感到骄傌Ӏ?#8221;"+
"博斯克还说。对于博斯克在首发中排出了久疏战늚坎比亚烦Q赛后有记者提Z质疑Q认为完全应该将队内的另一 "+
"名球员帕文派遣上Z加强后卫Uѝ对于这一疑议Q博斯克拒绝承担所谓的“责Q”Q认为球队的首发没有问题?#8220;我们按照整个赛季以来的方式做了,"+
"对于人员上的变化我没有什么可说的?#8221;对于球队在本赛季的前景,博斯克表C皇马还有西甲联赛的冠军作ؓ目标?#8220;皇家马d里在冠军 "+
"杯中战斗C最后,我们在联赛中也将q么做?#8221;"+
"A Java User Group is a group of people who share a common interest in
Java technology and meet on a regular basis to share"+
" technical ideas and information. The actual structure of a JUG can
vary greatly - from a small number of friends and coworkers"+
" meeting informally in the evening, to a large group of companies based in the same geographic area. "+
"Regardless of the size and focus of a particular JUG, the sense of community spirit remains the same. ";
outputAnalyzer(a,input);
//此处我已l对大文本进行过试,不会有问题效果很?
outputAnalyzer(a,"我爱 大家 ,Q?I love China 我喜Ƣ唱?");
assertAnalyzesTo(a,"我爱 大家 ,Q。I love China 我喜Ƣ唱?,
new String[]{"?," 大家 ","i","love","china","喜欢","唱歌"});
}
}
]]> [转]lucene学习W记? 几个问题 http://www.aygfsteel.com/super2/archive/2008/10/29/237299.html淘声依旧 淘声依旧 Wed, 29 Oct 2008 02:00:00 GMT http://www.aygfsteel.com/super2/archive/2008/10/29/237299.html http://www.aygfsteel.com/super2/comments/237299.html http://www.aygfsteel.com/super2/archive/2008/10/29/237299.html#Feedback 0 http://www.aygfsteel.com/super2/comments/commentRss/237299.html http://www.aygfsteel.com/super2/services/trackbacks/237299.html
我爱北京天安?你喜Ƣ吗.
我搜:北京
获取l果如何获取: 北京天安?.
不要用substring或者正则解决了.那样对于大文本不是解x? 因ؓq个数据没必要全取出?
|上也有人问: 做全文检索时Q想把查询到的附q的一D|本提取出来,像google那样Q如何才能性能根好Q?感觉indexof substringq些东性能会很差,如果是很大的文本 不知道大家有什么根好的办法Q获取什么其它组Ӟ
按照?term vectors 中增加了 位置和偏UM息?Grant Ingersoll & Christoph)的bug修改后的提示.应该可以扑ֈ.
2, 高亮昄. 下面有一例子说明. Z?.0的那个bug说明也脓(chung)C?
Lucene 中文分词?highlight 昄
下面q个需要外的包: lucene-highlighter-2.2.0.jar 支持.请下? 否则里面关于高亮昄的都不会~译成功. 下面E序是没有问题的.l果也对.是有版主说的问?
lucene2.0 中文高亮的问题。新手问老问题,知道的大虾赐?
代码Q?
public static void main(String[] args) {
try {
String text="上v麦ؓ公N易发展有限公?;
StandardAnalyzer ssss=new StandardAnalyzer();
QueryParser queryParse = new QueryParser("company_name", ssss);
SimpleHTMLFormatter sHtmlF = new SimpleHTMLFormatter("<b>", "</b>");
Highlighter hh = new Highlighter(sHtmlF,new QueryScorer(queryParse.parse("公司")));
TokenStream t=ssss.tokenStream("company_name",new StringReader(text));
Token tttt=t.next();
System.out.println(hh.getBestFragment(t,text));
} catch (Exception ex) {
}
}
l果Q?
上v麦ؓ<b>?lt;/b>贸易发展有限<b>?lt;/b><b>?lt;/b>
两个问题:
1Q怎么让单?#8220;?#8221;不高亮。因为我只搜索了“公司”
2Q怎么实现<b>公司</b>q样的高亮,而不?lt;b>?lt;/b><b>?lt;/b>
{?
用中文分词器,,,StandardAnalyzer是单字分词的
1、分词问?
2、Highlighter highlighter =new Highlighter(new
SimpleHTMLFormatter("<fontcolor=red>","</font>"),new
QueryScorer(query));
需要有一个好的中文分词工P能分Z需要的词语Q然后加亮。比如你可以用ik-analyzer啊等{的?
2.0bug解决::
22. 增加?contrib/highlighter ?NullFragmenter , q对全文本加亮很有用?
(Erik Hatcher)
]]> [转]lucene学习W记六——Lucene的搜?IndexSearcher) http://www.aygfsteel.com/super2/archive/2008/10/29/237296.html淘声依旧 淘声依旧 Wed, 29 Oct 2008 01:58:00 GMT http://www.aygfsteel.com/super2/archive/2008/10/29/237296.html http://www.aygfsteel.com/super2/comments/237296.html http://www.aygfsteel.com/super2/archive/2008/10/29/237296.html#Feedback 0 http://www.aygfsteel.com/super2/comments/commentRss/237296.html http://www.aygfsteel.com/super2/services/trackbacks/237296.html Lucene包括很多U不同的搜烦方式Q首先生成一个检索器IndexSearcher searcher = new
IndexSearcher("Index_Path", new StandardAnalyzer(),
true)Q然后再调用searcher.search(query)Q其中典型的query查询方式有以下几U:
1Q按词条搜烦Q?strong>TermQueryQ即搜烦某一词条?br />
Ҏ(gu)如下QQuery query = new TermQuery(new Term("field", "keyword"));
其中参数field指欲查找的字D,keyword指欲索的关键字?/p>
2Q在某一范围cL索:RangeQuery
Ҏ(gu)如下QRangeQuery query = new RangeQuery(begin, end, include);
其中参数begin和end均是一个Term对象Q分别指在烦引中相应Term的v始位|和l束位置。include是一个boolean|true表是包含起始和结束位|,false表示不包含边界倹{?/p>
3Q多关键字的搜烦Q?strong>PhraseQuery
Ҏ(gu)如下Q?br />
PhraseQuery query = new PhraseQuery();
query.add(new Term("content","keyword1"));
query.add(new Term("content","keyword2"));
?
注意的是PhraseQuerycM有一个setSlopҎ(gu)Q该Ҏ(gu)用于讑֮一个称之ؓ"坡度"的变量,来确定关键字之间是否允许、允许多个无关词汇
存在。默认gؓ0Q即两个关键字之间无M词汇存在Q才能被搜烦到。设|该g后,只有当两个关键字之间无关词的数目于{于坡度值是Q才能被搜烦
到。(文章末尾l出了具体例子)
4Q用通配W搜索:WildcardQuery
使用Ҏ(gu)cM?Q,只不q字D늚关键字允怋?Q代表一个字W)?Q代表多个字W)
另外Q还有以下不同的搜烦Ҏ(gu)Q?/p>
“与或”搜烦BooleanQuery?/strong>使用前缀搜烦PerfixQuery?/strong>使用短语~搜烦PhrasePrefixQuery?/strong>模糊查询搜烦FuzzyQuery{?/strong>
/*
* 多关键字搜烦的例?/span>*/
package testlucene;
import org.apache.lucene.analysis.standard. * ;
import org.apache.lucene.document. * ;
import org.apache.lucene.index. * ;
import org.apache.lucene.search. * ;
public class PhraseQueryTest {
public static void main(String[] args) throws Exception{
Document doc1 = new Document();
doc1.add( new Field( " content " , " david mary smith robert " ,Field.Store.YES,Field.Index.TOKENIZED));
doc1.add( new Field( " title " , " doc1 " ,Field.Store.YES,Field.Index.TOKENIZED));
Document doc2 = new Document();
doc2.add( new Field( " content " , " david smith mary robert " ,Field.Store.YES,Field.Index.TOKENIZED));
doc2.add( new Field( " title " , " doc2 " ,Field.Store.YES,Field.Index.TOKENIZED));
Document doc3 = new Document();
doc3.add( new Field( " content " , " david smith robert mary " ,Field.Store.YES,Field.Index.TOKENIZED));
doc3.add( new Field( " title " , " doc3 " ,Field.Store.YES,Field.Index.TOKENIZED));
IndexWriter writer = new IndexWriter( " c:\\index " , new StandardAnalyzer(), true );
// writer.setUseCompoundFile(true); // 讄为合烦引格?/span>
writer.addDocument(doc1);
writer.addDocument(doc2);
writer.addDocument(doc3);
writer.close();
IndexSearcher searcher = new IndexSearcher( " c:\\index " );
Term word1 = new Term( " content " , " david " );
Term word2 = new Term( " content " , " mary " );
Term word3 = new Term( " content " , " smith " );
Term word4 = new Term( " content " , " robert " );
PhraseQuery query = new PhraseQuery();
query.add(word1);
query.add(word2);
query.add(word3);
query.setSlop(Integer.MAX_VALUE);
Hits hits = searcher.search(query);
Print.printResult(hits, " david and mary " );
}
}
]]> [转]lucene学习W记? http://www.aygfsteel.com/super2/archive/2008/10/29/237293.html淘声依旧 淘声依旧 Wed, 29 Oct 2008 01:54:00 GMT http://www.aygfsteel.com/super2/archive/2008/10/29/237293.html http://www.aygfsteel.com/super2/comments/237293.html http://www.aygfsteel.com/super2/archive/2008/10/29/237293.html#Feedback 0 http://www.aygfsteel.com/super2/comments/commentRss/237293.html http://www.aygfsteel.com/super2/services/trackbacks/237293.html Lucene实现Ҏ(gu)询结果的排序Q?/p>
Sort sort = new Sort(new SortField("isbn", false)); //单个字段
Sort sort = new Sort(new SortField[]{new SortField("isbn", false), new SortField("pbl_dt", true)}); //多个字段
其中,SortField的构造函CW二个参数能够确定是升序q是降序?trueQ降序; falseQ升?
提醒Q烦引中tokenized的字D|不能被排序的Q否则会抛异常?/p>
package com.lucene.search;
import java.io.File;
import java.io.IOException;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
public class Searcher {
public static void main(String[] args) throws Exception {
File indexDir = new File( " C:\\target\\index\\book " );
String q = " ?/span>" ;
if ( ! indexDir.exists() || ! indexDir.isDirectory()) {
throw new IOException();
}
search(indexDir, q);
}
public static void search(File indexDir, String q) throws Exception {
Directory fsDir = FSDirectory.getDirectory(indexDir);
IndexSearcher searcher = new IndexSearcher(fsDir);
// Sort sort = new Sort(new SortField("isbn", false));
Sort sort = new Sort( new SortField[]{ new SortField( " isbn " , false ), new SortField( " pbl_dt " , true )});
Term term = new Term( " content " , q.toLowerCase());
TermQuery termQuery = new TermQuery(term);
Hits hits = searcher.search(termQuery, sort);
System.out.println( " 共有 " + searcher.maxDoc() + " 条烦引,命中 " + hits.length() + " ?/span>" );
for ( int i = 0 ; i < hits.length(); i ++ ) {
int DocId = hits.id(i);
String DocName = hits.doc(i).get( " name " );
String DocIsbn = hits.doc(i).get( " isbn " );
String DocPblDt = hits.doc(i).get( " pbl_dt " );
System.out.println(DocId + " : " + DocName + " ISBN: " + DocIsbn + " PBLDT: " + DocPblDt);
}
}
}
]]> [转]lucene学习W记?/title> http://www.aygfsteel.com/super2/archive/2008/10/29/237284.html淘声依旧 淘声依旧 Wed, 29 Oct 2008 01:43:00 GMT http://www.aygfsteel.com/super2/archive/2008/10/29/237284.html http://www.aygfsteel.com/super2/comments/237284.html http://www.aygfsteel.com/super2/archive/2008/10/29/237284.html#Feedback 0 http://www.aygfsteel.com/super2/comments/commentRss/237284.html http://www.aygfsteel.com/super2/services/trackbacks/237284.html
SpanFirstQueryQ查找方式ؓ从Field的内容v始位|开始,在一个固定的宽度内查找所指定的词条?
SpanNearQueryQ功能类似PharaseQuery。SpanNearQuery查找所匚w的不一定是短语Q还有可能是另一个SpanQuery的查询结果作为整体考虑Q进行嵌套查询?
SpanOrQueryQ把所有SpanQuery查询l果l合hQ作为检索结果?
SpanNotQueryQ从W一个SpanQuery查询l果中,LW二个SpanQuery查询l果Q作为检索结果?
2, 多条件烦引关p?
BooleanClause用于表示布尔查询子句关系的类Q包
括:BooleanClause.Occur.MUSTQBooleanClause.Occur.MUST_NOTQBooleanClause.Occur.SHOULD?
有以?U组合:
1QMUST和MUSTQ取得连个查询子句的交集?
2QMUST和MUST_NOTQ表C查询结果中不能包含MUST_NOT所对应得查询子句的索结果?
3QMUST_NOT和MUST_NOTQ无意义Q检索无l果?
4QSHOULD与MUST、SHOULD与MUST_NOTQSHOULD与MUSTq用Ӟ无意义,l果为MUST子句的检索结果。与MUST_NOTq用Ӟ功能同MUST?
5QSHOULD与SHOULDQ表C?#8220;?#8221;关系Q最l检索结果ؓ所有检索子句的q?
]]> [转]lucene学习W记?各种query http://www.aygfsteel.com/super2/archive/2008/10/29/237283.html淘声依旧 淘声依旧 Wed, 29 Oct 2008 01:42:00 GMT http://www.aygfsteel.com/super2/archive/2008/10/29/237283.html http://www.aygfsteel.com/super2/comments/237283.html http://www.aygfsteel.com/super2/archive/2008/10/29/237283.html#Feedback 0 http://www.aygfsteel.com/super2/comments/commentRss/237283.html http://www.aygfsteel.com/super2/services/trackbacks/237283.html
在创建烦引的时候,可以同时创徏多个IndexWriterQ将一个DocumentҎ(gu)需要拆分成多个包含部分Field的DocumentQƈ这些Document分别dC同的索引?
而在搜烦Ӟ则必d助ParallelReadercL整合?
Directory dir1=FSDirectory.getDirectory(new File(INDEX_DIR1),false);
Directory dir2=FSDirectory.getDirectory(new File(INDEX_DIR2),false);
ParallelReader preader=new ParallelReader();
preader.add(IndexReader.open(dir1));
preader.add(IndexReader.open(dir2));
IndexSearcher searcher=new IndexSearcher(preader);
之后的操作和一般的搜烦相同?
2, Query的子c? 下面的几个搜索在各种不同要求的场?都会用到. 需要大家仔l研?
Query query1 = new TermQuery(new Term(FieldValue, "name1")); // 词语搜烦
Query query2 = new WildcardQuery(new Term(FieldName, "name*")); // 通配W?
Query query3 = new PrefixQuery(new Term(FieldName, "name1")); // 字段搜烦 Field:KeywordQ自动在l尾d *
Query query4 = new RangeQuery(new Term(FieldNumber,
NumberTools.LongToString(11L)), new Term(FieldNumber,
NumberTools.LongToString(13L)), true); // 范围搜烦
Query query5 = new FilteredQuery(query, filter); // 带过滤条件的搜烦
Query query6 =new MatchAllDocsQuery(... // 用来匚w所有文?
Query query7 = new FuzzyQuery (...模糊搜烦
Query query8 = new RegexQuery (.. 正则搜烦
Query query9 = new SpanRegexQuery(...)?同上, 正则表达式的查询Q?
Query query9 = new SpanQuery 的子cd套其他SpanQuery 增加?rewriteҎ(gu)
Query query10 =new DisjunctionMaxQuery () ..c,提供了针Ҏ(gu)个短语的最大score。这一点对多字D늚搜烦非常有用
Query query11 = new ConstantScoreQuery cd包装了一?filter produces a score
equal to the query boost for every matching document.
BooleanQuery query12= new BooleanQuery();
booleanQuery.add(termQuery 1, BooleanClause.Occur.SHOULD);
booleanQuery.add(termQuery 2, BooleanClause.Occur.SHOULD);
//q个是ؓ了联合多个查询而做的Queryc? BooleanQuery增加了最的匚w短语。见QBooleanQuery.setMinimumNumberShouldMatch().
PhraseQuery
你可能对中日关系比较感兴,x?#8216;?#8217;?#8216;?#8217;挨得比较q(5个字的距dQ的文章Q超q这个距ȝ不予考虑Q你可以Q?
PhraseQuery query 13= new PhraseQuery();
query.setSlop(5);
query.add(new Term("content ", “?#8221;));
query.add(new Term(“content”, “?#8221;));
PhraseQuery对于短语的顺序是不管?q点在查询时除了提高命中率外,也会Ҏ(gu)能产生很大的媄? 利用SpanNearQuery可以对短语的序q行控制,提高性能
BooleanQuery query12= new SpanNearQuery 可以对短语的序q行控制,提高性能
3, 索引文本文g
如果你想把纯文本文g索引hQ而不惌己将它们d字符串创建fieldQ你可以用下面的代码创徏fieldQ?
Field field = new Field("content", new FileReader(file));
q里的file是该文本文件。该构造函数实际上是读L件内容,q对其进行烦引,但不存储
4, 如何删除索引
lucene提供了两U从索引中删除document的方法,一U是
void deleteDocument(int docNum)
q种Ҏ(gu)是根据document在烦引中的编h删除Q每个document加进索引后都会有个唯一~号Q所以根据编号删除是一U精删除,但是q个~号是烦引的内部l构Q一般我们不会知道某个文件的~号到底是几Q所以用处不大。另一U是
void deleteDocuments(Term term)
q种Ҏ(gu)实际上是首先Ҏ(gu)参数term执行一个搜索操作,然后把搜索到的结果批量删除了。我们可以通过q个Ҏ(gu)提供一个严格的查询条gQ达到删除指定document的目的?
下面l出一个例子:
Directory dir = FSDirectory.getDirectory(PATH, false);
IndexReader reader = IndexReader.open(dir);
Term term = new Term(field, key);
reader.deleteDocuments(term);
reader.close();
5, 如何更新索引
luceneq没有提供专门的索引更新Ҏ(gu)Q我们需要先相应的document删除Q然后再新的document加入索引。例如:
Directory dir = FSDirectory.getDirectory(PATH, false);
IndexReader reader = IndexReader.open(dir);
Term term = new Term(“title”, “lucene introduction”);
reader.deleteDocuments(term);
reader.close();
IndexWriter writer = new IndexWriter(dir, new StandardAnalyzer(), true);
Document doc = new Document();
doc.add(new Field("title", "lucene introduction", Field.Store.YES, Field.Index.TOKENIZED));
doc.add(new Field("content", "lucene is funny", Field.Store.YES, Field.Index.TOKENIZED));
writer.addDocument(doc);
writer.optimize();
writer.close();
但是?.9RC1中说?
新增c: org.apache.lucene.index.IndexModifier Q它合ƈ?IndexWriter ?
IndexReaderQ好处是我们可以增加和删除文档的时候不同担?synchronisation/locking 的问题了?
6, filerc?使用 Filter Ҏ(gu)索结果进行过滤,可以获得更小范围内更_的结果?有h? 注意它执行的是预处理Q而不是对查询l果q行qoQ所以用filter的代h很大的,它可能会使一ơ查询耗时提高一癑ր?
ISOLatin1AccentFilter ,?ISO Latin 1 字符集中的unaccentedcdW替?accented cdW?
DateFilter 日期qo?
RangeFileter ,?DateFilter 更加通用Q实?
LengthFilter c? 已经?contrib 攑ֈ?core 代码里。从 stream 中去掉太长和太短的单? StopFilter c? 增加了对处理stop words 的忽略大写处理
7,本条是一个用过滤的说明:
qo
使用 Filter Ҏ(gu)索结果进行过滤,可以获得更小范围内更_的结果?
举个例子Q我们搜索上架时间在 2005-10-1 ?2005-10-30 之间的商品?
对于日期旉Q我们需要{换一下才能添加到索引库,同时q必L索引字段?
// index
document.Add(FieldDate, DateField.DateToString(date), Field.Store.YES, Field.Index.UN_TOKENIZED);
//...
// search
Filter filter = new DateFilter(FieldDate, DateTime.Parse("2005-10-1"), DateTime.Parse("2005-10-30"));
Hits hits = searcher.Search(query, filter);
除了日期旉Q还可以使用整数。比如搜索h(hun)格在 100 ~ 200 之间的商品?
Lucene.Net NumberTools 对于数字q行了补位处理,如果需要用QҎ(gu)可以自己参考源码进行?
// index
document.Add(new Field(FieldNumber, NumberTools.LongToString((long)price), Field.Store.YES, Field.Index.UN_TOKENIZED));
//...
// search
Filter filter = new RangeFilter(FieldNumber, NumberTools.LongToString(100L), NumberTools.LongToString(200L), true, true);
Hits hits = searcher.Search(query, filter);
使用 Query 作ؓqo条g?
QueryFilter filter = new QueryFilter(QueryParser.Parse("name2", FieldValue, analyzer));
我们q可以?FilteredQuery q行多条件过滤?
Filter filter = new DateFilter(FieldDate, DateTime.Parse("2005-10-10"), DateTime.Parse("2005-10-15"));
Filter filter2 = new RangeFilter(FieldNumber, NumberTools.LongToString(11L), NumberTools.LongToString(13L), true, true);
Query query = QueryParser.Parse("name*", FieldName, analyzer);
query = new FilteredQuery(query, filter);
query = new FilteredQuery(query, filter2);
IndexSearcher searcher = new IndexSearcher(reader);
Hits hits = searcher.Search(query);
8, Sort
有时你想要一个排好序的结果集Q就像SQL语句?#8220;order by”Qlucene能做刎ͼ通过Sort?
Sort sort = new Sort(“time”); //相当于SQL?#8220;order by time”
Sort sort = new Sort(“time”, true); // 相当于SQL?#8220;order by time desc”
下面是一个完整的例子Q?
Directory dir = FSDirectory.getDirectory(PATH, false);
IndexSearcher is = new IndexSearcher(dir);
QueryParser parser = new QueryParser("content", new StandardAnalyzer());
Query query = parser.parse("title:lucene content:lucene";
RangeFilter filter = new RangeFilter("time", "20060101", "20060230", true, true);
Sort sort = new Sort(“time”);
Hits hits = is.search(query, filter, sort);
for (int i = 0; i < hits.length(); i++)
{
Document doc = hits.doc(i);
System.out.println(doc.get("title");
}
is.close();
9, 性能优化
一直到q里Q我们还是在讨论怎么样lucene跑v来,完成指定d。利用前面说的也实能完成大部分功能。但是测试表明lucene的性能q不是很
好,在大数据量大q发的条件下甚至会有半分钟返回的情况。另外大数据量的数据初始化徏立烦引也是一个十分耗时的过E。那么如何提高lucene的性能呢?
下面从优化创建烦引性能和优化搜索性能两方面介l?
9.1 优化创徏索引性能
q方面的优化途径比较有限QIndexWriter提供了一些接口可以控制徏立烦引的操作Q另外我们可以先烦引写入RAMDirectoryQ再扚w?
入FSDirectoryQ不怎样Q目的都是尽量少的文件IOQ因为创建烦引的最大瓶颈在于磁盘I(y)O。另外选择一个较好的分析器也能提高一些性能?
9.1.1 通过讄IndexWriter的参C化烦引徏?
setMaxBufferedDocs(int maxBufferedDocs)
控制写入一个新的segment前内存中保存的document的数目,讄较大的数目可以加快徏索引速度Q默认ؓ10?
setMaxMergeDocs(int maxMergeDocs)
控制一个segment中可以保存的最大document数目QD?yu)有利于q加索引的速度Q默认Integer.MAX_VALUEQ无需修改?
setMergeFactor(int mergeFactor)
控制多个segment合ƈ的频率,D大时建立索引速度较快Q默认是10Q可以在建立索引时设|ؓ100?
9.1.2 通过RAMDirectory~写提高性能
我们可以先把索引写入RAMDirectoryQ达C定数量时再批量写qFSDirectoryQ减磁盘I(y)Oơ数?
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);
while (there are documents to index)
{
... create Document ...
ramWriter.addDocument(doc);
if (condition for flushing memory to disk has been met)
{
fsWriter.addIndexes(new Directory[] { ramDir });
ramWriter.close();
ramWriter = new IndexWriter(ramDir, new StandardAnalyzer(), true);
}
}
9.1.3 选择较好的分析器
q个优化主要是对盘I间的优化,可以烦引文件减将q一半,相同试数据下由600M减少?80M。但是对旉q没有什么帮助,甚至会需要更长时
_因ؓ较好的分析器需要匹配词库,会消耗更多cpuQ测试数据用StandardAnalyzer耗时133分钟Q用MMAnalyzer耗时150?
钟?
9.2 优化搜烦性能
虽然建立索引的操作非常耗时Q但是那毕竟只在最初创建时才需要,qx只是量的维护操作,更何况这些可以放C个后台进E处理,q不影响用户搜烦。我们创建烦引的目的是l用h索,所以搜索的性能才是我们最兛_的。下面就来探讨一下如何提高搜索性能?
9.2.1 烦引放入内?
q是一个最直观的想法,因ؓ内存比磁盘快很多。Lucene提供了RAMDirectory可以在内存中容纳索引Q?
Directory fsDir = FSDirectory.getDirectory(“/data/index/”, false);
Directory ramDir = new RAMDirectory(fsDir);
Searcher searcher = new IndexSearcher(ramDir);
但是实践证明RAMDirectory和FSDirectory速度差不多,当数据量很小时两者都非常快,当数据量较大Ӟ索引文g400MQRAMDirectory甚至比FSDirectoryq要慢一点,q确实让人出乎意料?
而且lucene的搜索非常耗内存,即ɞ?00M的烦引文件蝲入内存,在运行一D|间后都会out of memoryQ所以个入内存的作用q不大?
9.2.2 优化旉范围限制
既然载入内存q不能提高效率,一定有其它瓉Q经q测试发现最大的瓉居然是时间范围限Ӟ那么我们可以怎样使时间范围限制的代h(hun)最呢Q?
当需要搜索指定时间范围内的结果时Q可以:
1、用RangeQueryQ设|范_但是RangeQuery的实现实际上是将旉范围内的旉点展开Q组成一个个BooleanClause加入?
BooleanQuery中查询,
因此旉范围不可能设|太大,l测试,范围过一个月׃抛BooleanQuery.TooManyClausesQ可以通过讄
BooleanQuery.setMaxClauseCount(int
maxClauseCount)扩大Q但是扩大也是有限的Qƈ且随着maxClauseCount扩大Q占用内存也扩大
2、用RangeFilter代替RangeQueryQ经试速度不会比RangeQuery慢,但是仍然有性能瓉Q查询的90%以上旉耗费?
RangeFilterQ研I其源码发现RangeFilter实际上是首先遍历所有烦引,生成一个BitSetQ标记每个documentQ在旉范围
内的标记为trueQ不在的标记为falseQ然后将l果传递给Searcher查找Q这是十分耗时的?
3、进一步提高性能Q这个又有两个思\Q?
a、缓存Filterl果。既然RangeFilter的执行是在搜索之前,那么它的输入都是一定的Q就是IndexReaderQ?
IndexReader是由Directory军_的,所以可以认为RangeFilter的结果是p围的上下限决定的Q也是由具体的
RangeFilter对象军_Q所以我们只要以RangeFilter对象为键Q将filterl果BitSet~存h卛_。lucene
API已经提供了一个CachingWrapperFiltercd装了Filter及其l果Q所以具体实施v来我们可以cache
CachingWrapperFilter对象Q需要注意的是,不要被CachingWrapperFilter的名字及其说明误
|CachingWrapperFilter看v来是有缓存功能,但的~存是针对同一个filter的,也就是在你用同一个filterqo不同
IndexReaderӞ它可以帮你缓存不同IndexReader的结果,而我们的需求恰恰相反,我们是用不同filterqo同一?
IndexReaderQ所以只能把它作Z个封装类?
b、降低时间精度。研IFilter的工作原理可以看出,它每ơ工作都是遍历整个烦引的Q所以时间粒度越大,Ҏ(gu)快Q搜索时间越短,在不影响功能的情况下Q时间精度越低越好,有时甚至牺牲一点精度也值得Q当然最好的情况是根本不作时间限制?
下面针对上面的两个思\演示一下优化结果(都采?00U程随机关键词随x间范_Q?
W一l,旉_ֺ为秒Q?
方式 直接用RangeFilter 使用cache 不用filter
q_每个U程耗时 10s 1s 300ms
W二l,旉_ֺ为天
方式 直接用RangeFilter 使用cache 不用filter
q_每个U程耗时 900ms 360ms 300ms
׃上数据可以得出结论:
1?量降低旉_ֺQ将_ֺq换成天带来的性能提高甚至比用cacheq好Q最好不使用filter?
2?在不能降低时间精度的情况下,使用cache能带?0倍左右的性能提高?
9.2.3 使用更好的分析器
q个跟创建烦引优化道理差不多Q烦引文件小了搜索自然会加快。当然这个提高也是有限的。较好的分析器相对于最差的分析器对性能的提升在20%以下?
10 一些经?
10.1关键词区分大写
or AND TO{关键词是区分大写的,lucene只认大写的,写的当做普通单词?/strong>
10.2 d互斥?
同一时刻只能有一个对索引的写操作Q在写的同时可以q行搜烦
10.3 文g?
在写索引的过E中退出将在tmp目录留下一个lock文gQ以后的写操作无法q行Q可以将其手工删?
10.4 旉格式
lucene只支持一U时间格式yyMMddHHmmssQ所以你传一个yy-MM-dd HH:mm:ss的时间给lucene它是不会当作旉来处理的
10.5 讄boost
有些时候在搜烦时某个字D늚权重需要大一些,例如你可能认为标题中出现关键词的文章比正文中出现关键词的文章更有价|你可以把标题的boost讄的更大,那么搜烦l果会优先显C标题中出现关键词的文章Q没有用排序的前题下)。用方法:
Field. setBoost(float boost);默认值是1.0Q也是说要增加权重的需要设|得?大?
上面q篇关于性能的讲解是很深? 请学?
]]> [转]lucene学习W记? 1.9版本升的问? http://www.aygfsteel.com/super2/archive/2008/10/29/237282.html淘声依旧 淘声依旧 Wed, 29 Oct 2008 01:41:00 GMT http://www.aygfsteel.com/super2/archive/2008/10/29/237282.html http://www.aygfsteel.com/super2/comments/237282.html http://www.aygfsteel.com/super2/archive/2008/10/29/237282.html#Feedback 0 http://www.aygfsteel.com/super2/comments/commentRss/237282.html http://www.aygfsteel.com/super2/services/trackbacks/237282.html
注:lucene2.0发布版本q不?00%的和1.4.3版兼宏V也是说在你用2.0版本的Lucene开发包替换原来?.4.3版本Ӟ应该让你的应用程序首先和1.9的兼宏V?
使用前提Q?
1. ~译和用Lucene需?Java1.4 或以上版本?
Lucene 1.9 在运行时的变化:
1. 模糊搜烦 FuzzyQuery 不再抛出 TooManyClauses 异常。当 FuzzyQuery 扩展多于
BooleanQuery.maxClauseCount ?Q只有最相关的term会被重新写入query,因此避免了异常的抛出?
(Christoph)
2. 把系l属?"org.apache.lucene.lockdir" 改ؓ "org.apache.lucene.lockDir"?Bernhard)
1.9 RC1
注:lucene2.0发布版本q不?00%的和1.4.3版兼宏V也是说在你用2.0版本的Lucene开发包替换原来?.4.3版本Ӟ应该让你的应用程序首先和1.9的兼宏V?
使用前提Q?
1. ~译和用Lucene需?Java1.4 或以上版本?
Lucene 1.9 在运行时的变化:
1. 模糊搜烦 FuzzyQuery 不再抛出 TooManyClauses 异常。当 FuzzyQuery 扩展多于
BooleanQuery.maxClauseCount ?Q只有最相关的term会被重新写入query,因此避免了异常的抛出?
(Christoph)
2. 把系l属?"org.apache.lucene.lockdir" 改ؓ "org.apache.lucene.lockDir"?Bernhard)
3. RangeQueries ?FuzzyQueries 默认被{换成写?(as it has been the case for
PrefixQueries and WildcardQueries before).使用
setLowercaseExpandedTerms(false) 来禁止大写自动转换的行为;同样也媄?PrefixQueries ?
WildcardQueries?Daniel Naber)
4. 在?MultiSearcher 的时候文档频率也可以正确计算Q全局性的计算各个 subsearchers ?indices
中。以前计的时候只?locally 的,每个 index 的计是分开的,q样引发的一个问题是Q在多个indices中rank
是不相等的?
(Chuck Williams, Wolf Siberski via Otis, bug #31841)
5. 在打开 IndexWriter 使用 create=true 参数QLucene
现在只是删除index目录中属于Lucene自己的文件? 判断文g名后~的方?)。原来是删除整个目录中的所有文件?Daniel
Naber and Bernhard Messer, bug #34695)
6. IndexReader 的版?Q可以通过 getCurrentVersion() ?getVersion()
q回。以前如果是新的indexes 那么q回的是0 。现在则用系l的毫秒数来初始化?(Bernhard Messer via Daniel
Naber)
7. 一些默认的初始化g再允讔R过 system properties 来设|。相反在 IndexWriter 中新增了相关?set/get Ҏ(gu)来设|相兛_性。主要包括以下属性:
?IndexWriter ?getter/setter Ҏ(gu)?
org.apache.lucene.writeLockTimeout, org.apache.lucene.commitLockTimeout,
org.apache.lucene.minMergeDocs, org.apache.lucene.maxMergeDocs,
org.apache.lucene.maxFieldLength, org.apache.lucene.termIndexInterval,
org.apache.lucene.mergeFactor,
q有 BooleanQuery ?getter/setter Ҏ(gu):
org.apache.lucene.maxClauseCount
q有 FSDirectory ?getter/setter Ҏ(gu)Q?
disableLuceneLocks
(Daniel Naber)
8. 修改?FieldCacheImpl Ҏ(gu)使用用户提供?IntParser ?FloatParser,来替代?Integer ?Float 的相x法?
(Yonik Seeley via Otis Gospodnetic)
9. 高搜烦q回?TopDocs ?TopFieldDocs 不再规范scores?
(Luc Vanlerberghe via Yonik Seeley, LUCENE-469)
1.9 的新Ҏ(gu):
1. 增加了对压羃字段存储的支持?patch #31149)
(Bernhard Messer via Christoph)
2. 增加了对压羃字段存储的支持?patch #29370)
(Bernhard Messer via Christoph)
3. ?term vectors 中增加了 位置和偏UM息?Grant Ingersoll & Christoph)
4. 增加了一个新?DateTools 。允许用h式化日期CU更可读的格式,以便于更好的适应索引。DateTools 不像
DateFields c,它允许日期指定到1970q以前,但必M用指定的日期格式。这P在RangeQuerys中用就更加有效率了?
(Daniel Naber)
5. QueryParser 现在可以正确的和Analyzers 一起工作了Q即可以在一个位|返回多?Token ?比如Q查询:
“+fast + car”如果 Analyzer 在同一位置q回 car ?automobile Q那么上面的查询被解析成:”+fast
+(car automobile)”?(Pierrick Brihaye, Daniel Naber)
6. 允许unbuffered的目录实现。(e.g.,using mmapQ?
InputStream 被新c?IndexInput 替换Q?BufferedIndexInput ?OutputStream 则被
IndexOutput ?BufferedIndexOutput?InputStream ?OutputStream
已经被废弃了。FSDirectory 现在是一个子cM?cutting)
7. 增加了原?Directory ?TermDocs 的实玎ͼ可以工作?GCJ 下。GCJ的版本需?3.4.0 以上。可以?ant gcj 来运行例子程序?cutting)
8. 增加?MmapDirectory c,它?nio to mmap 输入文g。现在MmapDirectory
比FSDirectory 要慢些。但他对每个查询term 使用更少的内存?cutting & Paul Elschot)
9. 增加 javadocs-internal ?build.xml – bug #30360
10. 增加?RangeFileter ,?DateFilter 更加通用Q实用?
(Chris M Hostetter via Erik)
11. 增加?NumberTools Q一个用来烦引数字字D늚工具cR? (adapted from code contributed by Matt Quail; committed by Erik)
12. 增加?public static IndexReader.main(String[] args) Ҏ(gu)?
IndexReader 现在可以直接在命令行方式下用,用来 列出或者从现存的烦引中抽取单独的文件出来?
(adapted from code contributed by Garrett Rooney; committed by Bernhard)
13. 增加 IndexWriter.setTermIndexInterval() Ҏ(gu)? (Doug Cutting)
14. 增加 LucenePackage ,q些静态的 get() Ҏ(gu)q回 java.util.Package。调用者可以用它来获得 Lucene jar 中的版本信息?
(Doug Cutting via Otis)
15. 增加 Hits.iterator() Ҏ(gu)和相应的 HitIterator ?Hit 对象。他提供了对 Hits对象标准?java.util.Iterator 叠代操作?
每个iterator's next() Ҏ(gu)q回一?Hit 对象? (Jeremy Rayner via Erik)
16. 增加 ParallelReaderQ这个一UIndexReader 他合q多个单独的索引C个单独的虚拟索引上?Doug Cutting)
17. 增加?FieldCache ?IntParser Q?FloatParser 接口, q样M格式的字D可以被以int 和float的Ş式缓存?
(Doug Cutting)
18. 新增c: org.apache.lucene.index.IndexModifier Q它合ƈ?IndexWriter ?
IndexReaderQ好处是我们可以增加和删除文档的时候不同担?synchronisation/locking 的问题了?(Daniel
Naber)
19. Lucene 现在可以被用在一个没有签名的applet中了QLucene’s dpȝ属性不会抛?SecurityException 异常?
(Jon Schuster via Daniel Naber, bug #34359)
20. 增加了新c?MatchAllDocsQuery 用来匚w所有文档?
(John Wang via Daniel Naber, bug #34946)
21. 当烦引太多的字段ӞZ消减索引大小和内存消耗,提供了忽略规范化字段的功能?
? Field.setOmitNorms() (Yonik Seeley, LUCENE-448)
22. 增加?contrib/highlighter ?NullFragmenter , q对全文本加亮很有用?
(Erik Hatcher)
23. 增加了正则表辑ּ的查询: RegexQuery ?SpanRegexQuery?
(Erik Hatcher)
24. 增加 ConstantScoreQuery c,它包装了一?filter produces a score
equal to the query boost for every matching document.
(Yonik Seeley, LUCENE-383)
25. 增加?ConstantScoreRangeQuery c,为某个区间的每个文档提供一个不变的 score。这个类比普通的
RangeQuery cȝ好处是它q不展开?BooleanQuery Q因此也不存在区间最大term上限?(Yonik Seeley,
LUCENE-383)
26. 为BooleanQuery增加了最的匚w短语。见QBooleanQuery.setMinimumNumberShouldMatch().
(Paul Elschot, Chris Hostetter via Yonik Seeley, LUCENE-395)
27. 增加?DisjunctionMaxQuery c,提供了针Ҏ(gu)个短语的最大score。这一点对多字D늚搜烦非常有用?
(Luc Vanlerberghe via Yonik Seeley, LUCENE-323)
28. 新增c:ISOLatin1AccentFilter ,?ISO Latin 1 字符集中的unaccentedcdW替?accented cdW? (Sven Duzont via Erik Hatcher)
29. 新增c:KeywordAnalyzer?Tokenizes" 整个作Z个单独的token。这个类对于 邮政~码Q序列号Q和产品名称{比较有用?
(Erik Hatcher)
30. ?LengthFilter cM contrib 攑ֈ?core 代码里。从 stream 中去掉太长和太短的单词? (David Spencer via Otis and Daniel)
31. 增加?getPositionIncrementGap Ҏ(gu)?Analyzer 中。这L戯定义?analyzer
可以在相同字D名的实例之间增加间?gapsQ用来防?phrase ?span 查询出边界。默认的 gap ?0 ?(Erik
Hatcher, with advice from Yonik)
32. StopFilter 增加了对处理stop words 的忽略大写处理? (Grant Ingersoll via Yonik, LUCENE-248)
33. 增加?TopDocCollector ?TopFieldDocCollector。用来简化实现hit 集合针对 top-scoring ?top-sorting hits的处理?
API 的改变:
1. 几个Ҏ(gu)和字D已l被废弃。在API 文档中包含了替换的内宏V在q些中,q些不徏议用的Ҏ(gu)和字D将会在Lucene2.0中被删除?
(Daniel Naber)
2. Russian ?German ?analyzers 被移C contrib/analyzers ?
同样 WordlistLoader cM被放C org.apache.lucene.analysis.WordlistLoader ? (Daniel Naber)
3. API 包含抛出 IOException 异常的声明,但是实际上不会抛出?These declarations have been removed. If
your code tries to catch these exceptions you might need to remove
those catch clauses to avoid compile errors.(Daniel Naber)
4. 为BooleanClause cȝenum 标准参数增加序列化的参数cR? (Christoph)
5. ?SpanQuery 的子cd套其他SpanQuery 增加?rewriteҎ(gu)?
Lucene 的源代码理器也从cvs 换到了svnQ? http://svn.apache.org/repos/asf/lucene/java/trunk
参考资料:http://blog.csdn.net/accesine960/archive/2006/02/28/612622.aspx
原文地址Q?a target="_blank">http://svn.apache.org/viewcvs.cgi/*checkout*/lucene/java/branches/lucene_1_9/CHANGES.txt?rev=379190
]]> [转]lucene学习W记一 记录开?/title> http://www.aygfsteel.com/super2/archive/2008/10/29/237276.html淘声依旧 淘声依旧 Wed, 29 Oct 2008 01:16:00 GMT http://www.aygfsteel.com/super2/archive/2008/10/29/237276.html http://www.aygfsteel.com/super2/comments/237276.html http://www.aygfsteel.com/super2/archive/2008/10/29/237276.html#Feedback 0 http://www.aygfsteel.com/super2/comments/commentRss/237276.html http://www.aygfsteel.com/super2/services/trackbacks/237276.html
1, 2005q的时? 听说了lucene. 是一个开源的搜烦引擎开发包. 而不是一个搜索引?请切?
2, 如果开始学习它, 需要至知?它所包含的包. 目前lucene已经C2.2版本. 当然你需要时d注他的最新版? 目前?
lucene-core-2.2.0.jar . 下蝲可以到apache的网站上下蝲. q一个就够了.不用下别?
3, 下面问题会接t而至, 我挨着?你挨着看即?
分词. W一个要涉及的问? 分词是一句话中的关键词汇分离出来, 然后才可以徏立烦? 例如 中华人民共和?--> 中华,
中华人民 华h,人民, 共和?{? lucene~省带了一个标准分词的c? StandardAnalyzer q个按字来分?
从网上发C很多E序员写的开源的分词的类.
当然都是l承了lucene的org.apache.lucene.analysis.Analyzec? 以实现更好更快的分词效果.
可以搜烦获取更多, 一般分词的c?都提供了可检分词效果的Ҏ(gu). 输入一个长? 然后执行,看看分词效果和执行时?
4, ThesaurusAnalyzer是一个哥们开发的,|上有源码可以下? 从这个源码里面对分词可以有更深入的了?
包括那些是词?那些不是词汇. 都在文本文g里面以行分割开? 由此可以知道: 分词是需要词库的. 因ؓ词库可以不断的扩?
.但每ơ构造分词对象时,是徏立在当前词库基础上的. 如果词库动态增加了新的词汇, 需要重新构建分词对? 当然, 也可以读取数据库.
5, 上面的分? 也仅仅是分词! |上有h提出的问题是: 索引?加入?东北大学". "北大" . 要搜?北大 ,
昄我们没有扑ֈ东北大学的意? 但最后还是找C. 因ؓ东北大学四个字里面有北大两个? 分词时这个词被确认是个词, 加入了索引.
q种情况, 涉及到汉语语义的问题 .暂时不好解决. 所以不?
选择较好的分析器
q个优化主要是对盘I间的优化,可以烦引文件减将q一半,相同试数据下由600M减少?80M。但是对旉q没有什么帮助,甚至会需要更长时
_因ؓ较好的分析器需要匹配词库,会消耗更多cpuQ测试数据用StandardAnalyzer耗时133分钟Q用MMAnalyzer耗时150?
钟?
6, 分词的缺? ׃乎同义词. Z减少用户搜烦的次? 增加搜烦效果. 如果用户?"北京 饭店" 能不能把" 首都 饭店"也列出来?
q个分词器无能ؓ? 我也考虑到这个问? 在北京托四公司的TRS的搜索品文档中人家也考虑Cq个问题. ׃乎如果搜?锐器,
pȝ会自动把匕首,刀{词汇一q加入搜索结? 所以这个问?,只能是在分词之?我们再加一?同义词返回模? q个思\很不?
也比较简? 很容易实? 关键是词库的建立. q个p到这?
7, 说到q里,你可能想要做个例子来实践一? 做个例子很容? |上很多. 我只做简单的叙述: lucene是用目录或者内存来存储数据?
可以讑֮.
但是实践证明RAMDirectory和FSDirectory速度差不多,当数据量很小时两者都非常快,当数据量较大Ӟ索引文g
400MQRAMDirectory甚至比FSDirectoryq要慢一点,q确实让人出乎意料?
而且lucene的搜索非常耗内存,即ɞ?00M的烦引文件蝲入内存,在运行一D|间后都会out of memoryQ所以个入内存的作用q不大?
我们用目?
如下:
//构徏一?IndexWriter 用来写如索引
File indexDir = new File(
"E:""javasource""LuceneTest""index");
IndexWriter indexWriter = new IndexWriter(indexDir,
new ThesaurusAnalyzer(), false);
Document doc = Document(new Article("name"+i, "北京老张"));
indexWriter.addDocument(doc);
indexWrite.close();
׃可以看出, lucene在q个目录下进行操? 上面代码中的你不要抄袭当例子, 因ؓq有一个ArticlecdDocumentҎ(gu).里面也有一些东? 现在仅仅先理解上面的意思即? 操作?你可能不知道他会在目录里q什?
8, 目录下的东西 . 如果试成功, 目录下有三个文g.
segments.gen segments_a08, q有一个类?_uw.cfs名字的东? 当然,不一定都一? 但肯定是q三? 如果出现了很多文?不要着? 看下面的 9 .
9, 如果lucene的烦引目录下出现了很多文? 肯定是有问题? 几个斚w.首先lucene在执行写操作?
会先在目录下写如一个write.lock的文仉定这个目?以避免别的烦引再操作q个路径. 否则那样肯定会ؕ. 锁定之后, 开始写索引,
写烦引时luceneZ几个或者几十个临时片段文g, 都似乎又短又q字符.cfs的文? 当烦引徏立完毕后,没有执行
indexWriter.optimize();Ҏ(gu), 他就不会合ƈ那些׃八糟的文? 所?索引建完? 一定要执行 上面的优化方?
保持目录下保?个文件即? 也就是很多时文件会合ƈC个文件中? 切不可大意删? 但当数据很多? 另行考虑{略.
10, lucene在写入烦引时, 用在索引目录下徏write.lock文g来标识锁? 而只有在执行close()Ҏ(gu)? 才会删除q个锁文? 只要q个文g存在, 其他的写索引的程序都会报?
caught a class org.apache.lucene.store.LockObtainFailedException
with message: Lock obtain timed out: SimpleFSLock@E:"javasource"LuceneTest"index"write.lock
所?需要注? 一定要注意关闭indexWrite. 包括异常?用finally关闭.否则会导致下一ơ写索引p|.
11, 扚w增加索引, 如果要成批的用@环加入烦?该怎么办呢. 首先h? IndexWriter indexWriter = new IndexWriter(indexDir,
new ThesaurusAnalyzer(), false); 最后一个参Cؓfalse表示持箋想烦引增加数? 如果为true, 则每ơ会删除全部, 重新开?
12, 在批量增加烦引时, E序可以一直执?
indexWriter.addDocument(doc); 但不能一直执行优?indexWriter.optimize();
因ؓ优化Ҏ(gu)比较耗时, 特别是当索引很大? 更要注意. 因ؓ优化, 也仅仅似乎优化会消耗很多时间和cpu.
所以这个时?多几个文件也没关p? |上有个人问了这L问题, 我摘录如? 用等号分割开我的内容:
引自:
http://www.javaeye.com/topic/107818?page=3
================================================
我不知道是不是理解错了增量烦引的概念
我搜索的|页不会重复,不是Ҏ(gu)有的|页都不停的?而是我搜索特定的|站.q里面不会出现重复现?每次爬到的网肯定是index里没有的
问一个问?
如果?0个网需要徏立index
?
IndexWriter iw=new IndexWriter(...);
for(int i=0;i<10;i++){
iw.addDocuemnt(doc);
}
iw.close();
q是
for(int i=0;i<10;i++){
IndexWriter iw=new IndexWriter(...);
iw.addDocuemnt(doc);
iw.close();
}
q有Q如果index量有10GQ做一ơoptimize需要多长时_
多长旉Optimize一ơ?
对一个刚刚做qOptimize的index目录做OptimizeQ会不会很快q束,q是也需要很长时_
optimizel束后是不是只剩?个文Ӟ如果有其他文Ӟ是不是意味着有问题呢Q(没有Reader或者Searcher在用这个index的时候)
q回端 最后更? 2007-08-10 11:02 (0) (0) 正在投票?..
amigobot {: 初会员
文章: 28
U分: 14
旉: 2007-08-12 14:15 引用 收藏
--------------------------------------------------------------------------------
没有必要6分钟一ơ?每次optimize都会重新做烦引, 光拷?0G文g得多少分钟Q如果不是频J删除的话, 一天, 甚至一C拜一都可以?选择pȝ负蝲的时候就行?
q回端 最后更? 2007-08-12 14:15 (0) (0) 正在投票?..
licco1 {: 初会员
文章: 22
U分: 0
旉: 2007-09-06 09:43 引用 收藏
--------------------------------------------------------------------------------
1:当search动作太频J?或者访问的人很?在optimize时会出现q个message
java.io.IOException: Cannot delete E:"index"_nir.f2;
注意查下是不是每ơ查询完都把indexReaderlclose了。你可以试下,频繁的开searchQ如果还有这个异常,估计是没把
indexReaderlcloseQ千万不要以为close the indexSearcher
ok了,要注意新建indexSearcher时传的参数是什么,是Direcitory,q是indexReaderQ还是字W串文g路径Q这影响?
否close indexReaderQ?
q回端 最后更? 2007-09-06 09:43 (0) (0) 正在投票?..
fool_leave {: 初会员
性别:
文章: 21
U分: 0
来自: 上v
旉: 2007-09-07 09:44 引用 收藏
--------------------------------------------------------------------------------
新徏indexReader时传入的是index file pathQ而且在search完毕后都在finally里面做了close动作?
BTWQ我把optimize动作L后,也就是说无论它运行多久都不让他optimzeQ结果index很正常,文g数量不会增加很多Qsearch也okay?
问题是M能老这样呀Q一直不optimize也不行呀。我做一ơoptimizeQ就要n分钟Qindex文g太大Q没办法?
而且我的index动作是针对不同的|页Q比?a target="_blank">http://xxx.xxx.xxx/1.html 被index后,以后遇到q个面׃会再做index动作。换句话_每次index的内定w是新的,不会覆盖以前的东ѝ这L需求是不是不用optimize呀?
q回端 最后更? 2007-09-07 09:44 (0) (0) 正在投票?..
licco1 {: 初会员
文章: 22
U分: 0
旉: 2007-09-07 10:09 引用 收藏
--------------------------------------------------------------------------------
fool_leaveQ你用的lucene版本是多?如果?.2的话Q可以用indexwriterQ以前用2.0Q我用indexReader执行
删除操作也出现过cM的情况(怀疑是indexreader只将被删除的documents讄了下删除的标志,在close的时候没真正执行删除动作Q?
也许是我执行了一个步骤,=会去看看reader的删除操作)。如果因为文件太大导致优?optimzeQ它的作用是重新整理D,把document
的id重新讄Q这个对搜烦效率很有帮助Q和document里term的内Ҏ(gu)关系)的时间很长,那就得重新考虑下你的架构了(10g太大?。这个得
h下imjl.
q回端 最后更? 2007-09-07 10:12 (0) (0) 正在投票?..
dwangel {:
文章: 500
U分: 650
圈子: TODOtree-ruby
旉: 2007-09-07 12:38 引用 收藏
--------------------------------------------------------------------------------
讄旉dQ凌?点启动indexWriterq行optimise?
启动前前台页面切换到昄l护的状态,然后{待所有的reader,searcher关闭Q然后进行optimise。(当然只有一个writer在跑Q?
In environments with frequent updates, optimize is best done during low volume times, if at all.
摘自lucene的文?
http://lucene.zones.apache.org:8080/hudson/job/Lucene-Nightly/javadoc/org/apache/lucene/index/IndexWriter.html#optimize ()
It is best not to re-open readers while optimize is running.
q句话我不是很明白,我觉得应该是说不要在optimizeq行时打开新的reader。但是用的re-openQ难道是?
不要在optimizeӞ重置reader。的状态?
q回端 最后更? 2007-09-07 12:48 (0) (0) 正在投票?..
licco1 {: 初会员
文章: 22
U分: 0
旉: 2007-09-07 17:29 引用 收藏
--------------------------------------------------------------------------------
因ؓif some but not all readers re-open while the optimize is underway,
this will cause > 2X temporary space to be consumed as those new
readers will then hold open the partially optimized segments at that
time.所以It is best not to re-open readers while optimize is
running.在进行优化的时候最好不要新开readers(2.2里好像没有reopenq个Ҏ(gu)吧,2.3里估计会?Q因为新的readers?
时会打开部分优化q的D,索引耗损的时空间会大于两倍烦引大?译错了g的一定要指出来哦)?
我觉得在做优化时Q不会对searcher有媄响,不必关闭搜烦功能?
q回端 最后更? 2007-09-07 17:31 (0) (0) 正在投票?..
fool_leave {: 初会员
性别:
文章: 21
U分: 0
来自: 上v
旉: 2007-09-10 09:56 引用 收藏
--------------------------------------------------------------------------------
thanks
无论是不是reopen,optimize都会耗用更多的space来存储时文?但这些都是时文?在动作结束后会被释放?所以如果硬盘空间够,q些多余的耗用应该不是大问题?
但我的index目录d?GQ我把旧的document删除了)。不q每ơoptimize一栯p很长旉。我不知道应该如何重新设|document的id.我的lucene version?.0的?
lucene的optimize的结果除了将index的文件数变成3个,q有什么好处呢Q到现在我看来只有在delete索引节点后有必要通过
optimize真正的把q些节点删除Q其他的优势g非常不明显。(因ؓ我每ơ写入index的烦引内定w是新的,不会有重复或q加现象Q。我现在d
把optimize从程序里L了,q行到现在已l?个月了,每分钟都有新内容加进去,但index目录依然很正常,文g?4个,从文件的修改旉上来
看也很正常。search动作也很正常?
如果一ơoptimize需要花?分钟以上的时_而这个操作又是不可中断的Q一旦在optimizeq程中终止了E序Q就会出现l(f)ucene自n无法恢复问题。这样对于程序要求太高了。对于服务器理也要求太高了?
=========================================
上面的内Ҏ(gu)些多, 不过也对大家有益. 他说最后他把执行优化的代码L?q行很好. 对于大数据量的来? q是个经? 除非采用冗余的机? 而不能对正在使用的数据进行优化操? 会造成用户讉Kd.
׃面可见的, 我就不说?
13,
索引q程中的L时刻、Q意进E都能对索引文gq行优化Q而且q样做也不会损坏索引文g或其不能被搜烦Q但是在索引q程中对索引q行优化的做法ƈ不值得
提倡。优化操作的最x机是在烦引过E结束之后,且当你确认在此后的一D|间内不会对烦引文件进行更改的时候。在索引q程中进行优化只会优化操作耗费?
多的旉?请大家݅取这个思想)
14, q是优化, 些h? 我用lucene做了一个Search Engine
E序q行也很正常Q但如果q箋q行几个月,有时会出现磁盘空间不的情况 .
通过iw.addDocument(doc)写入index
当list里的东西全部被写入完毕后Q通过optimze来优化烦?
可这个东西运行不是很E_Q有的时候很正常Q运行几个月都okayQ有?个月出现问题了。会在index的目录里出现很多文g。这些文件似乎是应该?
optimize掉的?一个烦引只能有一个indexreader, 在optimize的时候可以有多个indexsearcher在工作?
你得保
-->optimize实调用?
-->optimize的时候, 得有双倍的盘I间. 可见优化的代?
15 ,面的lucene都是在一个目录里面的, 大家也都看到? 也就是如果这个文件一直很大怎么? 首先到的第一个问题是是文g大小限制. 首先面的是一个大目录问题.
16, lucene的性能试:
下面l出一些测试数据,如果你觉得可以接受,那么可以选择?
试一Q?50万记录,300M左右文本Q生成烦?80M左右Q?00U程下^均处理时?00ms?
试二:37000记录Q烦引数据库中的两个varchar字段Q烦引文?.6MQ?00U程下^均处理时?.5ms?
17 . 分布搜烦
我们可以使用 MultiReader ?MultiSearcher 搜烦多个索引库?
MultiReader reader = new MultiReader(new IndexReader[] {
IndexReader.Open(@"c:"index"), IndexReader.Open(@"""server"index") });
IndexSearcher searcher = new IndexSearcher(reader);
Hits hits = searcher.Search(query);
?
IndexSearcher searcher1 = new IndexSearcher(reader1);
IndexSearcher searcher2 = new IndexSearcher(reader2);
MultiSearcher searcher = new MultiSearcher(new Searchable[] { searcher1, searcher2 });
Hits hits = searcher.Search(query);
q可以?ParallelMultiSearcher q行多线Eƈ行搜索?
18. 合ƈ索引?
?directory1 合ƈ?directory2 中?
Directory directory1 = FSDirectory.GetDirectory("index1", false);
Directory directory2 = FSDirectory.GetDirectory("index2", false);
IndexWriter writer = new IndexWriter(directory2, analyzer, false);
writer.AddIndexes(new Directory[] { directory });
Console.WriteLine(writer.DocCount());
writer.Close();
19. 昄搜烦语法字符?
我们l合了很多种搜烦条gQ或许想看看与其对等的搜索语法串是什么样的?
BooleanQuery query = new BooleanQuery();
query.Add(query1, true, false);
query.Add(query2, true, false);
//...
Console.WriteLine("Syntax: {0}", query.ToString());
输出Q?
Syntax: +(name:name* value:name*) +number:[0000000000000000b TO 0000000000000000d]
呵呵Q就q么单?
20. 操作索引?
删除 (软删除,仅添加了删除标记。调?IndexWriter.Optimize() 后真正删除?
IndexReader reader = IndexReader.Open(directory);
// 删除指定序号(DocId)?Document?
reader.Delete(123);
// 删除包含指定 Term ?Document?
reader.Delete(new Term(FieldValue, "Hello"));
// 恢复软删除?
reader.UndeleteAll();
reader.Close();
增量更新 (只需?create 参数设ؓ falseQ即可往现有索引库添加新数据?
Directory directory = FSDirectory.GetDirectory("index", false);
IndexWriter writer = new IndexWriter(directory, analyzer, false);
writer.AddDocument(doc1);
writer.AddDocument(doc2);
writer.Optimize();
writer.Close();
21. 优化
扚w?FSDirectory 增加索引Ӟ增大合ƈ因子(mergeFactor )和最文档合q数(minMergeDocs)有助于提高性能Q减烦引时间?
IndexWriter writer = new IndexWriter(directory, analyzer, true);
writer.maxFieldLength = 1000; // 字段最大长?
writer.mergeFactor = 1000;
writer.minMergeDocs = 1000;
for (int i = 0; i < 10000; i++)
{
// Add Documentes...
}
writer.Optimize();
writer.Close();
相关参数说明
转自《深?Lucene 索引机制?
利用
LuceneQ在创徏索引的工E中你可以充分利用机器的g资源来提高烦引的效率。当你需要烦引大量的文gӞ你会注意到烦引过E的瓉是在往盘上写?
引文件的q程中。ؓ了解册个问? Lucene 在内存中持有一块缓冲区。但我们如何控制 Lucene 的缓冲区呢?q运的是QLucene
的类 IndexWriter 提供了三个参数用来调整缓冲区的大以及往盘上写索引文g的频率?
22Q合q因?(mergeFactor)
q个参数军_了在 Lucene 的一个烦引块中可以存攑֤文档以及把盘上的索引块合q成一个大的烦引块的频率。比如,如果合ƈ因子的值是
10Q那么当内存中的文档数达?10 的时候所有的文档都必d到磁盘上的一个新的烦引块中。ƈ且,如果盘上的索引块的隔数辑ֈ 10 的话Q这
10 个烦引块会被合ƈ成一个新的烦引块。这个参数的默认值是
10Q如果需要烦引的文档数非常多的话q个值将是非怸合适的。对批处理的索引来讲Qؓq个参数赋一个比较大的g得到比较好的索引效果?
23Q最合q文档数 (minMergeDocs)
q个参数也会影响索引的性能。它军_了内存中的文档数臛_辑ֈ多少才能它们写回磁盘。这个参数的默认值是10Q如果你有够的内存Q那么将q个值尽量设的比较大一些将会显著的提高索引性能?
24Q最大合q文档数 (maxMergeDocs)
q个参数军_了一个烦引块中的最大的文档数。它的默认值是 Integer.MAX_VALUEQ将q个参数讄为比较大的值可以提高烦引效率和索速度Q由于该参数的默认值是整型的最大|所以我们一般不需要改动这个参数?
25 , Ҏ(gu)官方文档:从中可以分析出,如果在optimize索引的时候,也同时用Searcher。烦引空间的使用情况如下Q?
1. 原始索引
2. 由IndexWriter使用的烦引,用于optimize
3. 由IndexSearcher使用的烦引,用于搜烦?
所以要三倍的正常I间.
Z么需要优化?
管未经优化的烦引在大多数应用程序中都能够很好地q行工作Q但在那些处理大扚w索引的应用程序中Q用优化过的烦引会l应用程序带来更多的好处。特别是
在搜索操作需要长旉打开多个索引文g的情况下Q更能体现出索引被优化后的优势,因ؓ使用优化q的索引可以减少需要打开的文件描q符的个?
优化所需的磁盘空?
值得指出的是QLucene对一个烦引的优化操作是通过把已存在的段合ƈ成一个全新的D|完成的,q些已存在段的内Ҏ(gu)l会在新的段中表C出来。因而在q?
行优化时Q用的盘I间会有明显的增加。在新段创徏完成ӞLucene删除q移除这些旧Dc因此,在旧的段q没有被删除之前Q烦引占用的盘I间会变
成原来的两倍,因ؓ此时新段和旧D都会存储在索引中。在优化完成后,所占用的磁盘空间会降回C化前的状态。请CQ烦引优化的对象可以是多文g索引或复
合烦引?
26 , 索引文g有大限制吗Q?译)
某些 32 位操作系l限制每个文件不能大?2GB?
解决Ҏ(gu)Q?
1. 使用 IndexWriter.setMaxMergeDocs() 减小 MaxMergeDocs 数倹{?
2. 使用多个索引库。用复合烦?
27, IndexWriter.SetUseCompoundFile(true) 有什么用Q?
在创建烦引库Ӟ会合q多?Segments 文gC?.cfs 中。此方式有助于减烦引文件数量,减少同时打开的文件数量。原因:
某些操作pȝ会限制同时打开的文件数量?
解决Ҏ(gu)Q?
1. 使用 IndexWriter's setUseCompoundFile(true) 创徏复合文gQ减烦引文件数量?
2. 不要?IndexWriter's mergeFactor 的D|过大。尽这能加快烦引速度Q但会增加同时打开的文件数量?
3. 如果在搜索时发生该错误,那么你最好调?IndexWriter.Optimize() 优化你的索引库?
4. 认你仅创徏了一?IndexSearcher 实例Qƈ且在所有的搜烦U程中共用?原文Q?Make sure you only
open one IndexSearcher, and share it among all of the threads that are
doing searches -- this is safe, and it will minimize the number of
files that are open concurently. " 晕~~~Q究竟要怎么做? )
28, Z么搜索不到结果?(译)
可能原因Q?
. 搜烦字段没有被烦引?
. 索引库中的字D|有分词存储,无法和搜索词语进行局部匹配?
. 搜烦字段不存在?
. 搜烦字段名错误,注意字段名称区分大小写。徏议对字段名进行常量定义?
. 要搜索的词语是忽略词(StopWords)?
. 索引(IndexWriter)和搜?IndexSearcher)所使用?Analyzer 不同?
. 你所使用?Analyzer 区分大小写。比如它使用?LowerCaseFilterQ而你输入的查询词和目标大写不同?
. 你烦引的文档(Document)太大。Lucene 为避免造成内存不(OutOfMemory)Q缺省仅索引?0000个词?Term)。可以?IndexWriter.setMaxFieldLength() 调整?
. 认在搜索前Q目标文档已l被d到烦引库?
. 如果你用了 QueryParserQ它可能q没有按照你所设想的去分析 BooleanQuerySyntax?
如果q不行,那么Q?
. 使用 Query.ToString() 查看I竟搜烦了些什么?
. 使用 Luke 看看你的索引库究竟有什么?
29, 上面的luke是查看烦引库? 我下载了一个版? 居然LC我l他的烦引\径不?无奈. .
30 ,
QueryParser 是线E安全的吗?
不是?
31, 说说分布式数据存? 支持lucene的分布式搜烦是 hadoop. q个也是apache下的属于lucene的开源项?
但目前的我看只支持linux的分布机? |上很多q个斚w? 据说开发hadoop的h已经Myahoo.
让hadoop支撑雅虎的分布式搜烦. 所以按说功能强?2006q的一月䆾Nutch和Lucene的缔造者Doug
Cutting加入了Yahoo公司Q从那时PYahoo开始进行Hadoop的部|与研究. 但网上有, q个分布式效率不?
参数如下:
l测试,Hadoopq不是万用灵丹,很取决于文g的大和数量Q处理的复杂度以及群集机器的数量Q相q的带宽Q当以上四者ƈ不大Ӟhadoop优势q不明显?
比如Q不用hadoop用java写的单grep函数处理100M的log文g只要4U,用了hadoop local的方式运行是14U,用了hadoop单机集群的方式是30U,用双机集?0M|口的话更慢Q慢C好意思说出来的地步?
? 怎么评h(hun)上面的哥们测试结果呢. 但愿他说的不? 因ؓ如果q样, yahoo不就M..
32, MaxDoc() ?DocCount()、NumDocs() 有什么不同?
MaxDocs() 表示索引库中最大的 Document ID P׃中间的某?Document 可能被删除,因此不能使用
MaxDocs() 来表C?Document
数量。IndexWriter.DocCount()、IndexReader.NumDocs()?
IndexSearcher.Reader.NumDocs() 都表C烦引库?Document 数量?
33, Z么同时进行搜索和更新会引?FileNotFoundException 异常Q?译)
可能原因Q?
1. 某个搜烦或更新对象禁用了锁?
2. 搜烦和更C用了不同?lockDir?
3. 索引库被存放?NFS (or Samba) 文gpȝ上?
管搜烦是只L作,?IndexSeacher Z获取索引文g列表Q也必须打开旉定烦引库。如果锁没有正确讄Q那么它?yu)取回一个错误的文g列表(此时 IndexWriter 可能正在d或优化烦?Q从而导致该异常发生?
34, write.lock 有什么用Q哪些类会用到它Q?译)
write.lock 用来协调索引库的q发修改处理?
?IndexWriter 打开索引库,或?IndexReader 删除文档旉创锁?
35. commit.lock 文g有什么用Q哪些类会用到它Q?译)
commit.lock 在调整烦引库 segments 文g内容时用?IndexReader ?IndexWriter 都会使用到它?
36, 如何更新已经索引的文档? (译)
你只能先删除Q然后添加更新后的文档?
使用 IndexWriter.addIndexes(IndexReader[]) ?IndexWriter.addIndexes(Directory[]) 合ƈ索引库有什么不同? (译)
使用 Directory[] 参数所需的文件句柄和内存较小Q烦引文件仅需打开一ơ,而?IndexReader[] 参数则需要打开所有的索引库?
]]> 《Lucene in action》中推荐的Lucene分页方式 http://www.aygfsteel.com/super2/archive/2008/10/28/237109.html淘声依旧 淘声依旧 Tue, 28 Oct 2008 06:36:00 GMT http://www.aygfsteel.com/super2/archive/2008/10/28/237109.html http://www.aygfsteel.com/super2/comments/237109.html http://www.aygfsteel.com/super2/archive/2008/10/28/237109.html#Feedback 0 http://www.aygfsteel.com/super2/comments/commentRss/237109.html http://www.aygfsteel.com/super2/services/trackbacks/237109.html private List processHits(Hits hits, int startIndex, int endIndex) throws Exception{
if (endIndex >= hits.length())
endIndex = hits.length() - 1 ;
List docs = new ArrayList();
for ( int i = startIndex;i <= endIndex;i ++ ){
Document doc = hits.doc(i);
Map docMap = new HashMap();
docMap.put( " id " ,doc.getField( " id " ).stringValue());
docMap.put( " name " ,doc.getField( " name " ).stringValue());
docMap.put( " price " ,doc.getField( " price " ).stringValue());
docs.add(docMap);
}
return docs;
}
]]>
վ֩ģ壺
ǿ |
|
|
ܿ |
|
|
|
ɽʡ |
|
|
Ϫ |
|
ղ |
|
ƺ |
|
ǿ |
Դ |
ؿ˹ |
|
Դ |
|
|
|
̨ǰ |
|
|
|
|
ƽ |
ԭ |
|
|
ɽ |
|
|
ؼ |
DZ |
ɽ |
|
Ұ |