用go构建个简单的搜索(一)
demo计划
- 后续持续补充
工具 | 说明 |
---|---|
切词器 | gse |
倒排索引 | 字典树 |
测试 | 网上下txt的小说 |
简单的demo初版问题
- go学习写个简单的字典树 之前写的字典树需要优化,就是节点需要额外存储一些数据(索引
- 索引如何构建类型 定义了一个简单的结构体,统计现在只有个词频
- 索引保存磁盘、加载 没处理,暂且不知道怎么处理
- 后续可以通过切词器提取提取词的位置 没处理
大概流程
读取文件
切词器去掉停词标点符号
载入字典树
关键字查找索引信息
字典树处理的遇到的问题
搞了很久,做测试的时候:家珍和家人一样的结果,我用rune取得长度直接取字符了,导致只判断了前两个字节,go字符串中unicode中文三个字节,所以前面两个字节相同的。
go中中文的字符串根据下标的遍历的时候需要特殊处理下,如果是其他语言过来的需要注意下
for _, str := range str1 {
fmt.Printf("%c", str)
}
for index := 0; index < len([]rune(str2)); index++ {
//fmt.Println(str2[index])
fmt.Println([]rune(str2)[index])
}
效果图
切词器和文本搜索有点出入但是差别不大
字典树结构定义
// 文档描述
type docDes struct {
Id uint32 //编号
Type uint8 //类型
Path string //路径
Term string //单词
Count uint32 //词频 Term Frequency
Desc string //描述
//位置
}
type dictTree struct {
str rune //当前的字符
isDict bool //是否表示一个单词
doc []*docDes //文档
child []*dictTree //子节点
}
文件加载,没分段直接加载到内存了
func fileLoad(strPath string) (string, error) {
file, err := os.Open(strPath)
if err != nil {
fmt.Println("文件打开失败", err)
}
//及时关闭file句柄
defer file.Close()
fileinfo, err := file.Stat()
if err != nil {
fmt.Println(err)
return "", err
}
filesize := fileinfo.Size()
buffer := make([]byte, filesize)
bytesread, err := file.Read(buffer)
if err != nil {
fmt.Println(err)
return "", err
}
//转换 https://juejin.cn/post/7009826389851373605
return byteSliceToString(buffer[:bytesread]), nil
}
切词
var seg gse.Segmenter
func init() {
seg.LoadDict()
}
/**
* 去除标点符号和停词
*/
func getSplicWord(str string) []string {
return seg.Stop(seg.Trim(seg.Cut(str, true)))
}
转载自:https://juejin.cn/post/7240351482255671357