本文介绍一下.fdt 文件的存储格式。java
fdt 文件,以正排的方式,存储了 field 的原始真实数据。也就是说,你添加到全部中的全部 field 内容。都会存储在此文件中。数组
其中Header 和 Footer, 与其中文件并没有差异。详细字段解释能够看 Lucene 系列(二)索引格式之 fdm 文件缓存
这里主要看一下以 chunk 为单位进行存储的 field 信息。也就是图中的这一部。微信
其中。对于每个 chunk. 首先会存储一个 ChunkHeader:markdown
其中包括:ide
以后,会将当前 chunk 的全部 field 信息进行压缩存储。函数
其中依次罗列了全部的 doc, 每一个 doc 中罗列了全部的 field.oop
field 信息中,存储了:学习
对。fdt 文件的写入,主要是在CompressingStoredFieldsWriter
类中进行。编码
首先是在构造函数中写入 IndexHeader.
以后在每次调用flush(), 即每次缓存够一个 Chunk 时,进行 field 信息的写入。
在图中 1 处,写入ChunkHeader.
按序写入了DocBase, numBufferedDocs|Sliced, NumStoredFields, lengths
.
在图中 2 处,将当前缓冲的全部 field 信息进行压缩,写入。
内存中缓冲的 field 信息中包含哪些内容呢?这部分的写入在CompressingStoredFieldsWriter
类的writeField()
方法中。
/** * 写了什么? * 1.编号及类型 * 2. 内容 * 2.1 若是是基本类型,直接存储 * 2.2 若是是 bytes, 写长度和内容 * 2.3 若是是 string, 先写长度,而后写内容 */
@Override
public void writeField(FieldInfo info, IndexableField field) throws IOException {
// 计数+1
++numStoredFieldsInDoc;
int bits = 0;
final BytesRef bytes;
final String string;
Number number = field.numericValue();
if (number != null) {
if (number instanceof Byte || number instanceof Short || number instanceof Integer) {
bits = NUMERIC_INT;
} else if (number instanceof Long) {
bits = NUMERIC_LONG;
} else if (number instanceof Float) {
bits = NUMERIC_FLOAT;
} else if (number instanceof Double) {
bits = NUMERIC_DOUBLE;
} else {
throw new IllegalArgumentException("cannot store numeric type " + number.getClass());
}
string = null;
bytes = null;
} else {
bytes = field.binaryValue();
if (bytes != null) {
bits = BYTE_ARR;
string = null;
} else {
bits = STRING;
string = field.stringValue();
if (string == null) {
throw new IllegalArgumentException("field " + field.name() + " is stored but does not have binaryValue, stringValue nor numericValue");
}
}
}
// 存储了 field 的内部编号,以及当前 field 的类型,是四种数字呢,仍是字符串,仍是二进制串。
// number , 一个 int, 右边的 3 位是类型,左边的是编号
final long infoAndBits = (((long) info.number) << TYPE_BITS) | bits;
bufferedDocs.writeVLong(infoAndBits);
if (bytes != null) {
bufferedDocs.writeVInt(bytes.length);
bufferedDocs.writeBytes(bytes.bytes, bytes.offset, bytes.length);
} else if (string != null) {
bufferedDocs.writeString(string);
} else {
if (number instanceof Byte || number instanceof Short || number instanceof Integer) {
bufferedDocs.writeZInt(number.intValue());
} else if (number instanceof Long) {
writeTLong(bufferedDocs, number.longValue());
} else if (number instanceof Float) {
writeZFloat(bufferedDocs, number.floatValue());
} else if (number instanceof Double) {
writeZDouble(bufferedDocs, number.doubleValue());
} else {
throw new AssertionError("Cannot get here");
}
}
}
复制代码
如代码所示,首先分析了要存储 field 的类型及编码,以后将类型及编号写入一个 long, 以及 field 的真实信息,根据不一样的类型进行不一样的编码,以后缓冲到内存里,等到一个 chunk 写入完成或者最终调用 finish 时,批量的进行写入。
对 field 原始信息的写入比较简单。在每次添加一个 Document 时,循环调用添加 field. 将对应的 field 编号,类型,内容缓冲到内存里,每次缓冲够一个 Chunk, 进行压缩写入。
完。
以上皆为我的所思所得,若有错误欢迎评论区指正。
欢迎转载,烦请署名并保留原文连接。
更多学习笔记见我的博客或关注微信公众号 < 呼延十 >------>呼延十