用go构建个简单的搜索(三)对上篇索引文件优化
问题
上篇介绍了简单的索引文件结构,但是有个缺点是索引文件比源文件大太多了。所以这里想了些办法做了些尝试,最根本的原因是数据的位置信息越多越在后面占的数据量越多。
问题原因:
急忙|1|9|244916 244922|239419 239425|229922 229928|194147 194153|183813 183819|167921 167927|133701 133707|94319 94325|62012 62018
词|文档ID|词频|位置开始和结束1|位置开始和结束2|位置开始和结束3
急忙:本身的字节长度是6位,但是后面用了两个6位数的数字去去表示它的位置,并且还是多个位置
尝试的一些解决办法
首先想到的是位图但场景不合适
我想那么多坐标位置能不能用位图?然后在网上找了个代码还测出来个bug。最后失败告终。单个词位置信息量太少,但位图适合海量数据。举例上面急忙 总的9个位置18标识 需要244916/8=30,614.5 多个字节表示。如果数据量有244916么多倒是可以用,但是这里的6位数坐标需要6个字节就可以了。
再看这个索引的结构
- 发现单词的位置开始和结束之间都是当前切词的长度,(go中中文是3个字节需要注意),那直接保存开始坐标不就可以了,结束坐标可以根据当前字符串算出来,哈哈试了下有效果!
- 后面又做了点小的优化就是开始第一个坐标保存,后面的开始坐标保存的是第一个的差值,这个差值分布均匀后可能效果明显
func (doc *docDes) getPosStr() string {
if !doc.IsEmpty() {
//return fmt.Sprintf("%s|%d|%d|%s\n", doc.Term, doc.Id, doc.Count, doc.Position)
posArray := strings.Split(doc.Position, "|")
star := strings.Split(posArray[len(posArray)-1], " ")[0]
starNum, _ := strconv.Atoi(star)
postion := star + "|"//只保存开始坐标
for i := len(posArray) - 2; i >= 0; i-- {
currnt, _ := strconv.Atoi(strings.Split(posArray[i], " ")[0])
postion += fmt.Sprintf("%d", (currnt-starNum)) + "|" //计算差值保存
}
return fmt.Sprintf("%s|%d|%d|%s\n", doc.Term, doc.Id, doc.Count, postion)
} else {
return ""
}
}
转载自:https://juejin.cn/post/7241492331953356861