本文介紹一下.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, 進行壓縮寫入。
完。
以上皆爲我的所思所得,若有錯誤歡迎評論區指正。
歡迎轉載,煩請署名並保留原文連接。
更多學習筆記見我的博客或關注微信公衆號 < 呼延十 >------>呼延十