我们平时看到的文件,其本质上是有词组成的,我们可以看做是词的集合,当我们把相同的词就可以看做是一个词的向量了。
这里的tvx tvd tvf 就是以这种形式表示doc的:
tvx : doc的数量,以及每个doc 在 tvd 以及 tvf 中开始的位置。
tvd : 每个doc的域信息: 有多少个域,具体是那几个域,每个域向量在tvf文件中的位置,
tvf : 每个doc 的每域的 向量集合 ,向量集合中的每个元素就是一个 term: term文本,次数,位置等信息
这三者之间的关系,我们还是引用告诉的总结:
http://blog.csdn.net/forfuture1978/archive/2009/12/10/4976793.aspx
我们最后来看看源代码
if (vectors != null) {
final int numFields = vectors.length;
//字段的个数
tvd.writeVInt(numFields);
//因为tvd 中所有字段的 fieldnum 放一起,所有字段在tvf开始位置也放一起,所有遍历的时候,先保留在这里,最后一起写入文件
long[] fieldPointers = new long[numFields];
//处理每个字段
for (int i=0; i<numFields; i++) {
fieldPointers[i] = tvf.getFilePointer();
final int fieldNumber = fieldInfos.fieldNumber(vectors[i].getField());
// 写字段的序号
// 1st pass: write field numbers to tvd
tvd.writeVInt(fieldNumber);
//一个字段有多少个term
final int numTerms = vectors[i].size();
tvf.writeVInt(numTerms);
final TermPositionVector tpVector;
final byte bits;
final boolean storePositions;
final boolean storeOffsets;
//字段的一些bit位
if (vectors[i] instanceof TermPositionVector) {
// May have positions & offsets
tpVector = (TermPositionVector) vectors[i];
storePositions = tpVector.size() > 0 && tpVector.getTermPositions(0) != null;
storeOffsets = tpVector.size() > 0 && tpVector.getOffsets(0) != null;
bits = (byte) ((storePositions ? TermVectorsReader.STORE_POSITIONS_WITH_TERMVECTOR : 0) +
(storeOffsets ? TermVectorsReader.STORE_OFFSET_WITH_TERMVECTOR : 0));
} else {
tpVector = null;
bits = 0;
storePositions = false;
storeOffsets = false;
}
tvf.writeVInt(bits);
final String[] terms = vectors[i].getTerms();
final int[] freqs = vectors[i].getTermFrequencies();
int utf8Upto = 0;
utf8Results[1].length = 0;
//一个字段的所有term
for (int j=0; j<numTerms; j++) {
UnicodeUtil.UTF16toUTF8(terms[j], 0, terms[j].length(), utf8Results[utf8Upto]);
//采用前缀压缩
int start = StringHelper.bytesDifference(utf8Results[1-utf8Upto].result,
utf8Results[1-utf8Upto].length,
utf8Results[utf8Upto].result,
utf8Results[utf8Upto].length);
int length = utf8Results[utf8Upto].length - start;
tvf.writeVInt(start); // write shared prefix length
tvf.writeVInt(length); // write delta length
tvf.writeBytes(utf8Results[utf8Upto].result, start, length); // write delta bytes
utf8Upto = 1-utf8Upto;
final int termFreq = freqs[j];
tvf.writeVInt(termFreq);
if (storePositions) {
final int[] positions = tpVector.getTermPositions(j);
if (positions == null)
throw new IllegalStateException("Trying to write positions that are null!");
assert positions.length == termFreq;
// use delta encoding for positions
int lastPosition = 0;
for(int k=0;k<positions.length;k++) {
final int position = positions[k];
tvf.writeVInt(position-lastPosition);
lastPosition = position;
}
}
if (storeOffsets) {
final TermVectorOffsetInfo[] offsets = tpVector.getOffsets(j);
if (offsets == null)
throw new IllegalStateException("Trying to write offsets that are null!");
assert offsets.length == termFreq;
// use delta encoding for offsets
int lastEndOffset = 0;
for(int k=0;k<offsets.length;k++) {
final int startOffset = offsets[k].getStartOffset();
final int endOffset = offsets[k].getEndOffset();
tvf.writeVInt(startOffset-lastEndOffset);
tvf.writeVInt(endOffset-startOffset);
lastEndOffset = endOffset;
}
}
}
}
//写每个字段在tvf 中的位置,第一个已经在tvx文件中有了,所以这里不用写
// 2nd pass: write field pointers to tvd
if (numFields > 1) {
long lastFieldPointer = fieldPointers[0];
for (int i=1; i<numFields; i++) {
final long fieldPointer = fieldPointers[i];
tvd.writeVLong(fieldPointer-lastFieldPointer);
lastFieldPointer = fieldPointer;
}
}
} else
tvd.writeVInt(0);
}
1 首先在tvx 文件中写入 tvd 和tvf 开始的位置
2 在tvd中写入当前doc的字段的个数,然后遍历所有的字段,在tvd 中,写入每个字段的term 数目,已经每个term 具体信息在tvf中的位置, 最后写tvf信息,遍历每隔term ,写入每个term 信息。