C++ 基于正倒排索引的 Boost 搜索引擎实现
正倒排索引在搜索引擎项目中至关重要,两者协同工作以实现内容搜索。搜索引擎在对文档进行处理和索引构建时,会先创建正排索引,然后基于正排索引进一步生成倒排索引。当用户输入查询关键词时,搜索引擎会利用倒排索引快速定位包含该关键词的文档,再结合正排索引等其他信息进行结果展示。
1. 正倒排索引结构
1.1 正排索引
正排索引存储文档内容和其 ID。
// 正排索引中需要用到的结构体
typedef struct DocInfo {
std::string title; // 文档的标题
std::string content; // 文档的内容
std::string url; // 文档的 URL
int doc_id; // 文档的 ID
} DocInfo1;
1.2 倒排索引
倒排索引存储文档 ID、关键字及其权重。InvertedList 通常称为倒排拉链,因为一个关键字可能对应多个文档。
// 倒排索引中需要用到的结构体
struct InvertedElem {
int doc_id; // 文档的 ID
std::string word;// 关键字
int weight; // 文档的权重
};
typedef std::vector<InvertedElem> InvertedList;
2. 正倒排序部分 Class 的 Private 部分
2.1 准备工作
正排索引使用 vector,因为其下标即为文档 ID,使用便捷且减少代码量。倒排索引使用哈希表(unordered_map),通过关键字映射到倒排文档列表。
private:
// 正排索引使用 vector,因为它的下标就是文档的 id
std::vector<DocInfo1> forward_index;
// 使用哈希来进行映射
std::unordered_map<std::string, InvertedList> inverted_index;
2.2 单例模式
采用单例模式管理索引实例,好处包括:
- 减少资源浪费:避免反复创建或销毁实例导致的内存占用过高和 IO 开销增加。
- 确保全局逻辑统一:防止因多实例初始化参数不同导致搜索结果不稳定。
- 简化资源管理与调用:降低模块间耦合度,减少代码冗余。
需禁用拷贝构造函数和赋值运算符,并添加互斥锁以防止多线程并发创建多个实例。
private:
Index() {};
( Index&) = ;
Index& =( Index&) = ;
Index* instance;
std::mutex log;
:
~();
{
(instance == ) {
log.();
(instance == ) {
instance = ();
}
log.();
}
instance;
}


