nvd
,
nvm
文件主要描述的是索引阶段每个
Field
的域标准化值。
核心类图
图1(核心类图)
1⃣️NormsFormat
主要负责生成NormsProducer
和NormsConsumer
。
2⃣️NormsConsumer
主要负责对每个Field
生成normsValue,最终生成索引文件nvd
,nvm
。
3⃣️NormsProducer
主要负责生成normsValue,可以是读取索引文件nvd
,nvm
;也可以是通过其他方式,可以看NormsProducer
在源码中的多个实现类。
4⃣️在索引阶段,主要是通过NormValuesWriter
类的flush
方法来触发最终生成nvd
,nvm
文件。
写入过程
图2(写入过程)
org.apache.lucene.index.DefaultIndexingChain#writeNorms
private void writeNorms(SegmentWriteState state, Sorter.DocMap sortMap) throws IOException {
boolean success = false;
NormsConsumer normsConsumer = null;
try {
if (state.fieldInfos.hasNorms()) {
NormsFormat normsFormat = state.segmentInfo.getCodec().normsFormat();
assert normsFormat != null;
normsConsumer = normsFormat.normsConsumer(state);
for (FieldInfo fi : state.fieldInfos) {
PerField perField = getPerField(fi.name);
assert perField != null;
// we must check the final value of omitNorms for the fieldinfo: it could have
// changed for this field since the first time we added it.
if (fi.omitsNorms() == false && fi.getIndexOptions() != IndexOptions.NONE) {
assert perField.norms != null: "field=" + fi.name;
perField.norms.finish(state.segmentInfo.maxDoc());
//依次处理每一个Field的norm value 信息
perField.norms.flush(state, sortMap, normsConsumer);
}
}
}
success = true;
} finally {
if (success) {
IOUtils.close(normsConsumer);
} else {
IOUtils.closeWhileHandlingException(normsConsumer);
}
}
索引文件
nvd
nvd
可能是norm value data
的简写。
nvd, nvm
索引结构在nvd&&nvm这篇文章中解释的已经很详细了,这里仅做些补充。
Header
主要由6部分组成, 固定使用43
个字节。
1⃣️ int CODEC_MAGIC 表示header的开始,表示为4个字节
63, -41, 108, 23
2⃣️ string codec 固定字符串, “Lucene80NormsData”,表示为18个字节
17, 76, 117, 99, 101, 110, 101, 56, 48, 78, 111, 114, 109, 115, 68, 97, 116, 97
3⃣️int version = 表示为4个字节0, 0, 0, 0
4⃣️byte[] id 文件唯一标识符,16个字节,不固定
5⃣️segmentSuffixLength segment文件的后缀,因为没有后缀,长度为0,所以写入一个字节0
6⃣️segmentSuffix segment文件的后缀,因为没有后缀,所以这里不写入内容
nvm
个人认为是 norm values meta
的简写。
配合nvd
文件来存储norm values
信息。