Lucene索引在内存中的结构主要分为三个部分: field, term, docId,具体如下。
Field在内存中的组织结构
field->fileposition,域名对应在文件中的偏移量,TreeMap<String,Long> fields = new TreeMap<>();
.
具体代码在org.apache.lucene.codecs.simpletext.SimpleTextFieldsReader中的readFields()方法中。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16private TreeMap<String,Long> readFields(IndexInput in) throws IOException {
ChecksumIndexInput input = new BufferedChecksumIndexInput(in);
BytesRefBuilder scratch = new BytesRefBuilder();
TreeMap<String,Long> fields = new TreeMap<>();
while (true) {
SimpleTextUtil.readLine(input, scratch);
if (scratch.get().equals(END)) {
SimpleTextUtil.checkFooter(input);
return fields;
} else if (StringHelper.startsWith(scratch.get(), FIELD)) {
String fieldName = new String(scratch.bytes(), FIELD.length, scratch.length() - FIELD.length, StandardCharsets.UTF_8);
fields.put(fieldName, input.getFilePointer());
}
}
}
这里存放的value是偏移量。{content:234,keyword:456,title:767}
Term在内存中的组织结构
定义了一个有限状态机private FST<PairOutputs.Pair<Long,PairOutputs.Pair<Long,Long>>> fst;
fst的input即term的值,output有三个内容:
- term在倒排表中的偏移量,即在倒排表文件中的位置
- docFreq,即这个term在多少个文档中出现
- totalTermFreq,即这个term在文档中出现的总次数
具体源码在org.apache.lucene.codecs.simpletext.SimpleTextFieldsReader中的loadTerms()方法中。
1 | private void loadTerms() throws IOException { |
docId在内存中的组织结构
docid -> offset,private long offsets[]; /* docid -> offset in .fld file */
,文档id在索引文件(存储文档数据的文件)中的偏移量。
具体的数据结构是:[12,23,37,77……],数组的下标就是文档id,值就是文档在文件中的偏移量。
比如我们要取回文档0的值,那我们根据这个数组找到这个文档在文件中的偏移量是12,然后用随机读定位到文件的这个位置,接着就是read方法取回数据了.源代码在org.apache.lucene.codecs.simpletext.SimpleTextStoredFieldsReader的visitDocument()方法。
1 | public void visitDocument(int n, StoredFieldVisitor visitor) throws IOException { |
Lucene搜索时,索引在文件和内存中的状态
现在用一个搜索过程来看下如何加载和使用这些数据,我们使用的搜索条件是:title=hello
流程图如下