搜索引擎toy实现 by Python

1. 倒排表:

1. 第一列设计:
    1. 跳跃表
    2. Hash表 如果就中文还好说,cookie咋办冲突很大;不适合磁盘
    3. B+树,叶子节点存mmap offset;因为底层叶子顺序连接,适合多路归并;
    4. trie树
2. 第二列设计:倒排文件放磁盘,MMAP映射到内存

2. 文本相关性

3. 构建倒排索引:

先扫一次拿统计信息预计算,再建索引


1. 一次性全量:
    1. 遍历文档,设置doc_id
    2. 切词取term,拿到当前doc的term1,term2,…termn
    3. 建立{term: doc_id_list} 的dict
    4. 遍历完所有的文档,得到{term: doc_id_list} 大dict。
    5. 把大dict写入文件,记录{term: 文件offset}构建B+树
2. 分批合并:
    1. 内存中开固定空间
    2. 切词取term,拿到当前doc的term1,term2,…termn
    3. {term_1: doc_id}, {term_2: doc_id}…写进内存文档数据,保证按照term排序
    4. 前2步循环,内存空间用满了就写入磁盘,清空内存
    5. 合并磁盘文件,一个term生成它的倒排链追加到倒排文件中,词典铲屎这个term的offset
3. 结合:
    1. 设定n个文档写入一个段,按照第一种方法
    2. 搜索时候就多个段一期搜再出结果
    3. 段多了就合并

4. 构建正排索引,过滤使用

1. 以B+树为基础,
2. 对指定字段以list来做正排,[doc_1_price, doc_2_price, doc_3_price, … ,doc_n_price]
    1. 倒排拿到doc_id_list
    2. 去1维list筛选,满足price留下

5. 索引管理

1. 不同field支持不同的行为:完整匹配,过滤(<, >, 区间等)
2. 做1个field class来支持字段管理, add(), query(), filter(), get()

6. 段的管理,段就是一部分索引

1. 合并段
    1. 合并倒排,B+树是排序的,归并排序B+
    2. 合并正排,遍历append
2. 策略:每新增10万条数据持久化一个段,每到5个段将所有段合并成一个段

7. 索引层,增删改查

1. 删,bitmap,找到doc_id; 把bitmap第doc_id位置1标记删除;
2. 增:随机数-时间戳-本机IP(MAC)地址生成_id
3. 查:
    1. query分析/改写,最简单就是分词
    2. 倒排doc_id递增就是为了这一步求多个倒排list的交集
        1. 优化:取最短倒排链作标准,拿它每个元素去其他倒排链链比较,
            1. 如果发现某个元素不在某个倒排链中,那么他肯定不在最终结果中,直接跳出
            2. 如果某个倒排链被查找完了,那么也可以跳出了。
    3. 正排,过滤操作在这里
Comments
Write a Comment