当前位置: 首页 > news >正文

项目日记(3) boost搜索引擎

目录

1. 准备工作

2. 搜索初始化

3. 搜索部分

4. 对content部分处理

5. 服务器编写


前言: 上次在项目日记(2)写了index索引, 这次就可以进行search搜索了. 不多说快看. 先点个一键三联. 蟹蟹!!!

 1. 准备工作

后面需要倒排索引的结构体, 先准备好. words是后面一个文档里面出现的关键字.

    //倒排索引的结构struct InvertedElemPrint{uint64_t doc_id; //文档idint weight;      //文档权重vector<string> words;  //倒排关键字数组;InvertedElemPrint():doc_id(0),weight(0){}};

2.搜索初始化

前面创建的index进行构造单例; InitSearcher:初始化搜索, 就是创建index单例, 以及使用input文档建立索引;这些我们在index的时候都做好了直接引用即可.

class Searcher{private://索引indexns_index::Index* index;public:Searcher(){}~Searcher(){}public://搜索初始化, input就是文档内容//创建单例以及索引void InitSearcher(const string& input){//1.获取或者创建index对象;index = ns_index::Index::GetInstance();cout << "获取index单例成功..." << endl;//2.根据index对象建立索引;index->BuildIndex(input);cout << "建立正排倒排索引成功..." << endl;}

3. 搜索部分

1. 实现对query关键字进行分词; 并且存放到word里面, 前面我们写的util.hpp里面有进行分词的CutString直接使用;

2. 根据不同的分词建立索引, 因为我们在搜索的时候会有大小写, 但是结果是大小写不区分都能查出来.所以使用到boost标准库里面的to_lower接口; 根据关键词进行倒排索引, 通过倒排索引的结果填充倒排信息.

3.合并排序, 一个关键字可能对应多个文档; 根据权重进行排序;

4. 构建json, 根据查找出来的结果, 构建json串, 完成序列化和反序列化;

5. 还要对content的查找的关键字进行截取, GetDesc就是完成这个任务的.

//query是关键字, json_string返回给浏览器搜索结果.void Search(const string& query, string* json_string){//1.分词;将输入的关键字进行分词.并且用word存放vector<string> words;ns_util::JiebaUtil::CutString(query, &words);//2.触发; 根据不同的分词进行index, 忽略大小写.vector<InvertedElemPrint> inverted_list_all;//文档id和倒排结构unordered_map<uint64_t, InvertedElemPrint> tokens_map;for(string word : words){boost::to_lower(word);//根据分词关键字建立倒排索引, ns_index::InvertedList* inverted_lsit = index->GetInvertedIndex(word);//建立失败, 就继续;if(nullptr == inverted_lsit){continue;}//将倒排索引的结果用item接收.插入到文档内for(const auto& elem : *inverted_lsit){auto& item = tokens_map[elem.doc_id];item.doc_id = elem.doc_id;item.weight += elem.weight;item.words.push_back(elem.word); //文档关键字;}}for(const auto& item : tokens_map){inverted_list_all.push_back(move(item.second));}//3.合并排序; 因为一个关键字可能对应多个文档id.//降序;sort(inverted_list_all.begin(), inverted_list_all.end(), \[](const InvertedElemPrint& e1, const InvertedElemPrint& e2)\{return e1.weight > e2.weight;});//4.构建, 根据查找出来的结果,建立json串, jsoncpp, 完成序列化和反序列化;//创建json对象;Json::Value root;for(auto& item : inverted_list_all){//正排索引ns_index::DocInfo* doc = index->GetForwardIndex;if(nullptr == doc){continue;}Json::Value elem;elem["title"] = doc->title;elem["desc"] = GetDesc(doc->content, item.words[0]);elem["url"] = doc->url;elem["id"] = (int)item.doc_id;elem["weight"] = item.weight;root.append(elem);}Json::FastWriter writer;*json_string = writer.write(root);}

 4. 对content部分处理

GetDesc用来截取关键字前后内容的, search是algorithm库里面的接口进行查找.

string GetDesc(const string& html_content, const string& word){//找到word在html_content中首次出现, 以及前面50个和后面100个内容;const int prev_step = 50;const int next_step = 100;//1.找到关键词首次出现的地方;//tolower将大写转小写;auto iter = search(html_content.begin(), html_content.end(), word.begin(), word.end(), [](int x, int y){return (tolower(x) == tolower(y));});if(iter == html_content.end()){return "None1";}//distance返回两个迭代器的距离;int pos = distance(html_content.begin(), iter);//2.获取首次关键词前50到后100的位置;int start = 0;int end = html_content.size() - 1;if(pos > start + prev_step) start = pos - prev_step;if(pos < end - next_step) end = pos + next_step;//3.截取start和end的子串;if(start >= end) return "None2";string desc = html_content.substr(start, end - start);desc +="...";return desc; }

5. 服务器编写

这里使用到httplib的库, 自己可以到gitee里面查找下载到xshell里面就可以使用了.

首先初始化搜索.使用httplib建立库, 服务端获取关键字使用search将数据给json, 再使用客户端传递json.

#include <iostream>
#include "searcher.hpp"
#include "cpp-httplib/httplib.h"//原数据存放的地址;
const string input = "data/raw_html/raw.txt";
//目标网址.
const string root_path = "./wwwroot";int main()
{ns_searcher::Searcher search;search.InitSearcher(input);//使用到httplib库.并且建立服务端.httplib::Server svr;svr.set_base_dir(root_path.c_str());//服务端获取关键字, 使用json把数据读出来.svr.Get("/s", [](const httplib::Request& req, httplib::Response& rsp) {//如果没有输入搜索内容if(!req.has_param("word")){rsp.set_content("必须要输入搜索的关键字!", "text/plain; charset=utf-8");return;}//获取关键字;string word = req.get_param_value("word");cout << "用户在搜索" << word << endl;string json_string;//进行查找.search.Search(word, &json_string);//将内容进行连接.交给服务端.rsp.set_content(json_string, "application/json");});cout << "服务器编写成功..." << endl;svr.listen("0.0.0.0", 8081);return 0;
}

相关文章:

  • LabVIEW如何确保自动化设备的稳定性和可靠性?
  • RocketMQ使用(3):消息重复
  • 其它高阶数据结构⑦_Skiplist跳表_概念+实现+对比
  • 人工智能应用-实验8-用生成对抗网络生成数字图像
  • 计网(部分在session学习章)
  • Unity Physics入门
  • 【竞技宝】英超:足总杯踢完解雇腾帅,曼联管理层心意已决
  • 【设计模式深度剖析】【A】【创建型】【对比】| 工厂模式重点理解产品族的概念
  • memmove使⽤和模拟实现
  • 数据结构和算法基础(二)
  • 基于 Java 的浏览器——JxBrowser使用分享
  • Sass是什么?有哪些优缺点?
  • 【代码随想录算法训练营第37期 第十七天 | LeetCode110.平衡二叉树、257. 二叉树的所有路径、404.左叶子之和】
  • python数据类型之列表
  • 海外媒体发稿的关键步骤和投稿策略:如何撰写高质量的新闻稿?国外软文发布平台有哪些?
  • 【译】JS基础算法脚本:字符串结尾
  • angular2 简述
  • Apache Pulsar 2.1 重磅发布
  • CSS实用技巧
  • Docker入门(二) - Dockerfile
  • Java 11 发布计划来了,已确定 3个 新特性!!
  • Laravel 实践之路: 数据库迁移与数据填充
  • Protobuf3语言指南
  • SpingCloudBus整合RabbitMQ
  • vue-router 实现分析
  • webpack入门学习手记(二)
  • 安装python包到指定虚拟环境
  • 编写高质量JavaScript代码之并发
  • 高性能JavaScript阅读简记(三)
  • 解析 Webpack中import、require、按需加载的执行过程
  • 模型微调
  • 浅谈JavaScript的面向对象和它的封装、继承、多态
  • 详解NodeJs流之一
  • 云栖大讲堂Java基础入门(三)- 阿里巴巴Java开发手册介绍
  • No resource identifier found for attribute,RxJava之zip操作符
  • (1)Map集合 (2)异常机制 (3)File类 (4)I/O流
  • (23)Linux的软硬连接
  • (32位汇编 五)mov/add/sub/and/or/xor/not
  • (k8s中)docker netty OOM问题记录
  • (二)JAVA使用POI操作excel
  • (二十一)devops持续集成开发——使用jenkins的Docker Pipeline插件完成docker项目的pipeline流水线发布
  • (论文阅读40-45)图像描述1
  • (轉貼) 資訊相關科系畢業的學生,未來會是什麼樣子?(Misc)
  • ***通过什么方式***网吧
  • .cfg\.dat\.mak(持续补充)
  • .NET CLR Hosting 简介
  • .NET Core/Framework 创建委托以大幅度提高反射调用的性能
  • .NET 中让 Task 支持带超时的异步等待
  • .NET正则基础之——正则委托
  • .NET中使用Redis (二)
  • @Valid和@NotNull字段校验使用
  • [ HTML + CSS + Javascript ] 复盘尝试制作 2048 小游戏时遇到的问题
  • [ vulhub漏洞复现篇 ] Grafana任意文件读取漏洞CVE-2021-43798
  • [ 英语 ] 马斯克抱水槽“入主”推特总部中那句 Let that sink in 到底是什么梗?
  • [1159]adb判断手机屏幕状态并点亮屏幕