C++ 搜索引擎 Searcher 模块:基于正倒排索引的实现
Searcher 模块是对底层索引功能的封装,主要负责处理用户搜索请求并返回结果。
1. 单例模式
采用单例模式实例化索引对象,确保全局唯一性。
private: ns_index::Index* index;
public:
Searcher() {}
~Searcher() {}
public:
void InitSearcher(const std::string& input) {
// 获取单例 Index 对象
index = ns_index::Index::GetInstance();
// 根据输入建立索引
index->BuildIndex(input);
LOG1(NORMAL, "建立索引成功...");
}
2. Search
查询流程包括分词、触发、合并排序和构建 JSON 结果四个步骤。
2.1 分词
使用 Jieba 工具将用户关键字切分为单词数组。
2.2 触发
通过 index->GetInvertedList(w) 获取关键词对应的倒排索引列表。利用哈希表 tokens_map 自动去重,并通过 boost::to_lower 统一大小写。
2.3 合并
将去重后的倒排数据存入向量 inverted_list_all,并根据权重从大到小排序。
2.4 构建 JSON
序列化结果为标准 JSON 格式。使用 JsonCpp 库将内存中的 JSON 对象转换为可读字符串。
void Search(const std::string& query, std::string* json_string) {
// 1. 分词
std::vector<std::string> words;
ns_util::JiebaUtil::CutString(query, &words);
// 2. 触发与去重
std::vector<InvertedElemPrint> inverted_list_all;
std::unordered_map<uint64_t, InvertedElemPrint> tokens_map;
for (std::string w : words) {
boost::to_lower(w);
ns_index::InvertedList* inverted_list = index->(w);
(inverted_list == ) ;
( & elem : *inverted_list) {
& item = tokens_map[elem.doc_id];
item.doc_id = elem.doc_id;
item.weight += elem.weight;
item.words.(elem.word);
}
}
( & item : tokens_map) {
inverted_list_all.(std::(item.second));
}
std::(inverted_list_all.(), inverted_list_all.(), []( InvertedElemPrint& e1, InvertedElemPrint& e2) {
eweight > eweight;
});
Json::Value root;
(& item : inverted_list_all) {
ns_index::DocInfo* doc = index->(item.doc_id);
(doc == ) ;
Json::Value elem;
elem[] = doc->title;
elem[] = (doc->content, item.words[]);
elem[] = doc->url;
root.(elem);
}
Json::StyledWriter writer;
*json_string = writer.(root);
}


