lucene域(Field)的元数据信息(.fnm)

2012-04-27

一个段(Segment)包含多个域,每个域都有一些元数据信息,保存在.fnm文件中,.fnm文件的格式如下:

• FNMVersion
◦ 是fnm文件的版本号,对于Lucene 2.9为-2
• FieldsCount
◦ 域的数目
• 一个数组的域(Fields)
◦ FieldName:域名,如"title","modified","content"等。
◦ FieldBits:一系列标志位,表明对此域的索引方式
▪ 最低位:1表示此域被索引,0则不被索引。所谓被索引,也即放到倒排表中去。
▪ 仅仅被索引的域才能够被搜到。
▪ Field.Index.NO则表示不被索引。
▪ Field.Index.ANALYZED则表示不但被索引,而且被分词,比如索引"hello
world"后,无论是搜"hello",还是搜"world"都能够被搜到。
▪ Field.Index.NOT_ANALYZED表示虽然被索引,但是不分词,比如索引"hello
world"后,仅当搜"hello world"时,能够搜到,搜"hello"和搜"world"都搜不
到。
▪ 一个域出了能够被索引,还能够被存储,仅仅被存储的域是搜索不到的,但是
能通过文档号查到,多用于不想被搜索到,但是在通过其它域能够搜索到的情

况下,能够随着文档号返回给用户的域。

▪ Field.Store.Yes则表示存储此域,Field.Store.NO则表示不存储此域。
▪ 倒数第二位:1表示保存词向量,0为不保存词向量。
▪ Field.TermVector.YES表示保存词向量。
▪ Field.TermVector.NO表示不保存词向量。
▪ 倒数第三位:1表示在词向量中保存位置信息。
▪ Field.TermVector.WITH_POSITIONS
▪ 倒数第四位:1表示在词向量中保存偏移量信息。
▪ Field.TermVector.WITH_OFFSETS
▪ 倒数第五位:1表示不保存标准化因子
▪ Field.Index.ANALYZED_NO_NORMS
▪ Field.Index.NOT_ANALYZED_NO_NORMS
▪ 倒数第六位:是否保存payload

要了解域的元数据信息,还要了解以下几点:
• 位置(Position)和偏移量(Offset)的区别
◦ 位置是基于词Term的,偏移量是基于字母或汉字的。

• 索引域(Indexed)和存储域(Stored)的区别
◦ 一个域为什么会被存储(store)而不被索引(Index)呢?在一个文档中的所有信息中,有这样一部
分信息,可能不想被索引从而可以搜索到,但是当这个文档由于其他的信息被搜索到时,可以
同其他信息一同返回。
◦ 举个例子,读研究生时,您好不容易写了一篇论文交给您的导师,您的导师却要他所第一作者
而您做第二作者,然而您导师不想别人在论文系统中搜索您的名字时找到这篇论文,于是在论
文系统中,把第二作者这个Field的Indexed设为false,这样别人搜索您的名字,永远不知道您
写过这篇论文,只有在别人搜索您导师的名字从而找到您的文章时,在一个角落表述着第二作
者是您。

payload的使用
◦ 我们知道,索引是以倒排表形式存储的,对于每一个词,都保存了包含这个词的一个链表,当
然为了加快查询速度,此链表多用跳跃表进行存储。
◦ Payload信息就是存储在倒排表中的,同文档号一起存放,多用于存储与每篇文档相关的一些信
息。当然这部分信息也可以存储域里(stored Field),两者从功能上基本是一样的,然而当要存
储的信息很多的时候,存放在倒排表里,利用跳跃表,有利于大大提高搜索速度。

Payload主要有以下几种用法:
▪ 存储每个文档都有的信息:比如有的时候,我们想给每个文档赋一个我们自己的文档
号,而不是用Lucene自己的文档号。于是我们可以声明一个特殊的域(Field)"_ID"和特
殊的词(Term)"_ID",使得每篇文档都包含词"_ID",于是在词"_ID"的倒排表里面对于
每篇文档又有一项,每一项都有一个payload,于是我们可以在payload里面保存我们
自己的文档号。每当我们得到一个Lucene的文档号的时候,就能从跳跃表中查找到我
们自己的文档号。

//声明一个特殊的域和特殊的词
public static final String ID_PAYLOAD_FIELD = "_ID";
public static final String ID_PAYLOAD_TERM = "_ID";
public static final Term ID_TERM = new Term(ID_PAYLOAD_TERM, ID_PAYLOAD_FIELD);
//声明一个特殊的TokenStream,它只生成一个词(Term),就是那个特殊的词,在特殊的域里面。

static class SinglePayloadTokenStream extends TokenStream {
private Token token;
private boolean returnToken = false;
SinglePayloadTokenStream(String idPayloadTerm) {
char[] term = idPayloadTerm.toCharArray();
token = new Token(term, 0, term.length, 0, term.length);
}
void setPayloadValue(byte[] value) {
token.setPayload(new Payload(value));
returnToken = true;
}

public Token next() throws IOException {
if (returnToken) {
returnToken = false;
return token;
} else {
return null;
}
}
}

//对于每一篇文档,都让它包含这个特殊的词,在特殊的域里面
SinglePayloadTokenStream singlePayloadTokenStream = new SinglePayloadTokenStream(ID_PAYLOAD_TERM);
singlePayloadTokenStream.setPayloadValue(long2bytes(id));
doc.add(new Field(ID_PAYLOAD_FIELD, singlePayloadTokenStream));
//每当得到一个Lucene的文档号时,通过以下的方式得到payload里面的文档号

 long id = 0;

TermPositions tp = reader.termPositions(ID_PAYLOAD_TERM);
boolean ret = tp.skipTo(docID);
tp.nextPosition();
int payloadlength = tp.getPayloadLength();
byte[] payloadBuffer = new byte[payloadlength];
tp.getPayload(payloadBuffer, 0);
id = bytes2long(payloadBuffer);
tp.close();


▪ 影响词的评分
▪ 在Similarity抽象类中有函数public float scorePayload(byte [] payload, int
offset, int length) 可以根据payload的值影响评分。
• 读取域元数据信息的代码如下:

 

FieldInfos.read(IndexInput, String)
 int firstInt = input.readVInt();
 size = input.readVInt();
  for (int i = 0; i < size; i++)
  String name = input.readString();
  byte bits = input.readByte();
  boolean isIndexed = (bits & IS_INDEXED) != 0;
  boolean storeTermVector = (bits & STORE_TERMVECTOR) != 0;

boolean storePositionsWithTermVector = (bits &STORE_POSITIONS_WITH_TERMVECTOR) != 0;
boolean storeOffsetWithTermVector = (bits &STORE_OFFSET_WITH_TERMVECTOR) != 0;boolean omitNorms = (bits & OMIT_NORMS) != 0;
boolean storePayloads = (bits & STORE_PAYLOADS) != 0;
boolean omitTermFreqAndPositions = (bits &OMIT_TERM_FREQ_AND_POSITIONS) != 0;

PDF 55

 

作者:robotbird, 分类:关于代码 标签: lucene , 浏览(4668), 评论(1)
上一篇: lucene--文件格式3
下一篇: 罗马的故事-苏拉

相关文章

(1)条评论 订阅

  1. ${item.nickname} 惠头条 说:

    惠头条 看看资讯就可以赚钱。

1

发表评论

电子邮件用于回复通知和avatar全球唯一头像 *

*