Lucene Payload 的研究与应用

Please read full article from Lucene Payload 的研究与应用
在Lucene 2.1 中,记录位置信息的即 .prx 文件,它的格式如下:
ProxFile (.prx) --> <TermPositions> TermCount TermPositions --> <Positions> DocFreq Positions --> <PositionDelta> Freq PositionDelta --> VInt
仔细观察我们可以发现,文档 D0 中 what 词条是加粗显示而文档 D1 中的 what 则没有。显然,Lucene 2.1 的索引结构是无法表示出两者的差异。为了解决这个问题,从 Lucene2.2 开始,引入了 Payload 的概念。 Payload 即词条 (Term) 的元数据或称载荷, Lucene 支持用户在索引的过程中将词条的元数据添加的索引库中,同时也提供了在检索结果时读取 Payload 信息的功能
Payload 相关的 API
从 Lucene2.2 的索引结构可以看出,Payload 的存储与词条的位置信息是紧密联系在一起的,因此 Payload 的存储和检索 API 位于Token类和 TermPositions 类当中。
向词条中存储 Payload 信息
org.apache.lucene.analysis.Token void setPayload(Payload payload)
Payload 信息的构造函数
org.apache.lucene.index.Payload Payload(byte[] data) Payload(byte[] data, int offset, int length)
从位置信息中检索 Payload
org.apache.lucene.index.TermPositions boolean next(); int doc() int freq(); int nextPosition(); int getPayloadLength(); byte[] getPayload(byte[] data, int offset)
场景一:改进的 Lucene 的区间检索
日期检索是区间检索的常见例子,如用户需要在图书馆中检索特定年代的图书,满足如下条件:
Date>1954/08/01 & Date<1955/08/01
常见的做法就是将日期作为一个独立 Field 进行存储,利用 RangeQuery 进行区间检索,Posting-list 的格式如图3中左图所示。如果图书日期分布区间很广,用 Field 存储日期信息,我们需要将日期细化到年月日进行存储,因此词条数目是非常庞大的。这种情况下,我们可以利用 Payload 功能来减少词条的数目,提高检索效率,可以将日期的年月作为词条,日作为 Payload 信息,这几乎将词条数目减小了近 30 倍,改进后的存储结构如图3右图所示:
图 3:使用 Payload 存储日期信息
场景二:提高特定词汇的评分
利用 Payload 功能,还可以提高文档中特定词汇的评分,如黑体词汇、斜体词汇等,从而优化搜索结果排序。
下面还以文档 D0 和 D1 为例说明如何设置和检索 Payload。
D0 = "it is what it is" D1 = "what is it"
Step1:在Analyzer处理过程中,为特殊词汇添加评分Payload
final byte BoldBoost = 5; final byte ItalicBoost = 5; … Token token = new Token(…); … if (isBold) {//如果是黑体字 token.setPayload( new Payload(new byte[] {BoldBoost})); }else if(isItalic){//如果是斜体字 token.setPayload( new Payload(new byte[] { ItalicBoost })); } … return token;
Step2:重写Similarity (主要负责排名和评分)
Similarity boostingSimilarity = new DefaultSimilarity() { // @override public float scorePayload(byte [] payload, int offset, int length) { //读取payload的值,payload存储的即为词汇的评分。 if (length == 1) return payload[offset]; };
Step3:使用重写的boostingSimilarity进行检索
Query btq = new BoostingTermQuery( new Term(“field”, “what”)); Searcher searcher = new IndexSearcher(…); Searcher.setSimilarity(boostingSimilarity); … Hits hits = searcher.search(btq);
No comments:
Post a Comment