Searcher 类作为上层封装,负责调用底层索引文件并实现搜索功能。其核心职责是处理用户搜索词,并根据处理结果返回对应的网页信息。
1. 单例模式
这里采用单例模式实例化 Searcher,同时建立正倒排索引。
private: ns_index::Index* index;
public: Searcher(){}
~Searcher(){}
public: void InitSearcher(const std::string& input) {
// 1 创建(获取)一个 index 对象
// 在这里我们用的是单例模式
index=ns_index::Index::Getinstance();
// 2 根据对象建立索引
index->BuildIndex(input);
LOG1(NORMAL,"建立索引成功...");
}
2. Search 流程
该函数的主要流程包括分词、触发检索、合并排序和构建 JSON 结果四个步骤。
2.1 分词
先创建一个 words 数组,使用 CutString 函数把用户提供的关键字分词并交给 words。
2.2 触发
获取单例模式中的倒排索引,通过 index->GetInvertedList(w) 获取关键词 w 对应的倒排索引列表,然后存入 tokens_map。由于 tokens_map 是哈希结构,会自动实现去重。to_lower 用于实现小写化,避免区分大小写导致匹配失败。
在遍历倒排列表时,元素引用直接操作 tokens_map,确保效率。
2.3 合并
将处理好的倒排列表统一存入 inverted_list_all。之所以使用 vector 是因为访问更方便,接着根据自身的权重进行从大到小排序。
2.4 构建 JSON
这一步即序列化,将内容转变为标准的、线性的、可存储或可传输的格式。代码中通过 Json 库实现序列化,将单个序列化的结果交给总的 root。
Json::StyledWriter writer;
// ... root.append(elem);
*json_string=writer.write(root); // 完成序列化
注意:在这份代码里一会获取正排索引,一会获取倒排索引,但它们都与
inverted_list_all有关。inverted_list_all的本质是对多个倒排列表进行'去重、合并、排序'后的候选文档集合,是连接'索引查询'和'结果返回'的中间数据结构。
{
std::vector<std::string>words;
ns_util::JiebaUtil::(query,&words);
std::vector<InvertedElemPrint> inverted_list_all;
std::unordered_map<,InvertedElemPrint> tokens_map;
(std::string w:words) {
boost::(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);
}


