BoostCompass( 查找功能实现 )

news2024/10/6 12:19:20

在这里插入图片描述

阅读导航

  • 一、查找功能基本思路
  • 二、详细代码
  • 三、代码介绍
  • 四、运行结果

一、查找功能基本思路

通过实现一个基于倒排索引的搜索引擎,来提供高效、准确的搜索服务。其核心在于快速准确地从大量文档中检索出与用户查询关键词相关的文档,并按照相关性对结果进行排序。其中分为五个步骤:倒排索引的构建、分词处理、搜索查询处理、结果排序、结果格式化输出

  1. 倒排索引的构建:搜索引擎首先需要构建一个倒排索引,这是一种将文档中出现的每个单词与包含该单词的文档列表相关联的数据结构。这样,当用户发起搜索请求时,搜索引擎可以迅速找到包含特定关键词的所有文档。

  2. 分词处理:由于搜索引擎通常需要处理自然语言文本,因此对用户输入的查询字符串进行分词是必要的步骤。这样可以帮助搜索引擎更准确地匹配文档中的关键词。

  3. 搜索查询处理:用户发起的搜索请求会被处理成一系列的关键词查询。搜索引擎会利用倒排索引来查找每个关键词相关的文档,并根据一定的算法(如权重累加)合并这些结果。

  4. 结果排序:为了提供最相关的搜索结果,搜索引擎会对查询结果进行排序。通常,这会根据文档与查询关键词的相关性(如关键词出现的频率、位置等因素)来确定排序。

  5. 结果格式化输出:最后,搜索引擎会将排序后的搜索结果格式化为易于用户理解的形式,如JSON格式,这样用户或其他应用程序就可以方便地读取和使用这些结果。

通过这种方式,搜索引擎能够快速响应用户的查询请求,提供相关性强、准确度高的搜索结果,从而提升用户体验。

二、详细代码

⭕searcher.hpp

#pragma once

// 引入所需的头文件
#include "index.hpp"  // 索引库
#include "util.hpp"   // 工具库
#include "log.hpp"    // 日志库
#include <algorithm>  // C++ 标准库算法
#include <unordered_map>       // 哈希表容器
#include <jsoncpp/json/json.h> // JSON处理库

// 定义命名空间ns_searcher
namespace ns_searcher {
    // 定义用于打印的倒排元素结构体
    struct InvertedElemPrint {
        uint64_t doc_id; // 文档ID
        int weight; // 权重
        std::vector<std::string> words; // 包含的关键字
        InvertedElemPrint() : doc_id(0), weight(0) {} // 默认构造函数
    };

    // 定义搜索引擎类Searcher
    class Searcher {
    private:
        // 索引对象指针
        ns_index::Index *index;

    public:
        // 构造函数
        Searcher() {}
        // 析构函数
        ~Searcher() {}

        // 初始化搜索引擎
        void InitSearcher(const std::string &input) {
            // 获取或创建索引对象
            index = ns_index::Index::GetInstance();
            LOG(NORMAL, "获取index单例成功...");
            // 根据索引对象建立索引
            index->BuildIndex(input);
            LOG(NORMAL, "建立正排和倒排索引成功...");
        }

        // 执行搜索查询,query: 搜索关键字json_string: 返回给用户浏览器的搜索结果
        void Search(const std::string &query, std::string *json_string) {
            // 对查询关键字进行分词
            std::vector<std::string> words;
            ns_util::JiebaUtil::CutString(query, &words);

            // 准备用于存储搜索结果的结构
            std::unordered_map<uint64_t, InvertedElemPrint> tokens_map;
            std::vector<InvertedElemPrint> inverted_list_all;

            // 遍历分词结果,查询索引并合并结果
            for (std::string word : words) {
                boost::to_lower(word); // 转换为小写
                ns_index::InvertedList *inverted_list = index->GetInvertedList(word);
                if (inverted_list) {
                    for (const auto &elem : *inverted_list) {
                        auto &item = tokens_map[elem.doc_id]; // 获取或创建对应doc_id的InvertedElemPrint
                        item.doc_id = elem.doc_id;
                        item.weight += elem.weight;
                        item.words.push_back(elem.word);
                    }
                }
            }

            // 将合并后的结果添加到inverted_list_all
            for (const auto &item : tokens_map) {
                inverted_list_all.push_back(std::move(item.second));
            }

            // 根据权重降序排序搜索结果
            std::sort(inverted_list_all.begin(), inverted_list_all.end(),
                      [](const InvertedElemPrint &e1, const InvertedElemPrint &e2) {
                          return e1.weight > e2.weight;
                      });

            // 构建JSON格式的搜索结果
            Json::Value root;
            for (auto &item : inverted_list_all) {
                ns_index::DocInfo *doc = index->GetForwardIndex(item.doc_id);
                if (doc) {
                    Json::Value elem;
                    elem["title"] = doc->title;// 文档标题
                    elem["desc"] = GetDesc(doc->content, item.words[0]); // 获取描述
                    elem["url"] = doc->url; // 文档URL
                    elem["id"] = (int)item.doc_id; // 文档ID
                    elem["weight"] = item.weight; // 权重

                    root.append(elem);
                }
            }

            // 将JSON对象转换为字符串
            Json::FastWriter writer;
            *json_string = writer.write(root);
        }

        // 获取文档描述的辅助函数
        std::string GetDesc(const std::string &html_content, const std::string &word) {
            // 查找word在html_content中的首次出现位置
            auto iter = std::search(html_content.begin(), html_content.end(),
                                 word.begin(), word.end(), [](int x, int y) {
                                     return (std::tolower(x) == std::tolower(y));
                                 });
            if (iter == html_content.end()) {
                return "None1";
            }
            int pos = std::distance(html_content.begin(), iter);

            // 确定描述的起始和结束位置
            int start = pos - 50;
            int end = pos + 100;
            if (start < 0) start = 0;
            if (end > (int)html_content.size()) end = (int)html_content.size();

            // 截取描述内容并返回
            std::string desc = html_content.substr(start, end - start);
            desc += "...";
            return desc;
        }
    };
}

三、代码介绍

  1. 倒排元素结构体:在ns_searcher命名空间内部,定义了一个结构体InvertedElemPrint,用于存储文档ID、权重和包含的关键字。这个结构体用于打印和展示搜索结果中的倒排列表元素。

  2. 搜索引擎类:定义了一个名为Searcher的类,它是搜索引擎的核心。这个类包含一个指向索引对象的指针,该索引对象用于存储和管理文档数据。

  3. 构造函数和析构函数Searcher类有默认的构造函数和析构函数,用于初始化和销毁对象。

  4. 初始化搜索引擎InitSearcher方法用于获取或创建索引对象,并根据该索引对象建立正排和倒排索引。这是搜索引擎工作的前提。

  5. 执行搜索查询Search方法是搜索引擎的核心功能,它接收一个查询字符串,对该字符串进行分词处理,然后查询索引并合并搜索结果。搜索结果根据权重进行排序,并构建成JSON格式返回给用户。

  6. 分词处理:使用ns_util::JiebaUtil::CutString方法对查询字符串进行分词,这是中文文本处理中常见的步骤,以便更好地匹配文档中的关键词。

  7. 倒排索引查询:对于分词后的每个关键词,通过index->GetInvertedList方法查询倒排列表,并将结果合并到一个哈希表中。

  8. 结果排序和构建:合并后的搜索结果被添加到一个向量中,并根据权重进行降序排序。之后,构建JSON格式的搜索结果,包括文档标题、描述、URL和文档ID等信息。

  9. 获取文档描述的辅助函数GetDesc方法用于从HTML内容中提取包含特定关键词的描述性文本片段。它查找关键词在内容中的首次出现位置,并截取前后各50个字符作为描述内容。

四、运行结果

🥰如下图所示在搜索引擎的查询结果中,我们成功地提取了关键信息,包括文档的标题、摘要和URL。

在这里插入图片描述

✅这些信息为用户提供了一个直观的概览,使得用户能够快速识别和访问他们感兴趣的具体内容。标题作为文档的主题概述,摘要提供了内容的简短描述,而URL则直接指向了原始资源的网络地址。通过这种方式,用户可以高效地从搜索结果中筛选和导航到他们寻求的信息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1601428.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

小程序视频怎么保存到mp4

小程序上的视频如何下载成mp4&#xff0c;本文就将教大家如何将小程序视频保存到mp4&#xff0c;这里要用到一个工具:下载高手 下载高手的文件我已经打包好了 下载高手链接&#xff1a;https://pan.baidu.com/s/1qJ81sNBzzzU0w6DWf-9Nxw?pwdl09r 提取码&#xff1a;l09r -…

项目7-音乐播放器3(删除模块+播放音乐模块设计)

1.播放音乐模块设计 1.1 请求响应设计 请求&#xff1a; { get, /music/get?pathxxx.mp3 } 响应&#xff1a; { 音乐数据本身的字节信息 } 1.2 后端代码 1. Files.readAllBytes(String path) : 读取文件中的所有字节&#xff0c;读入内存 &#xff…

实体识别方法

文章目录 实体识别方法求观测序列的概率 实体识别方法 从文本中识别实体边界及其类型 实体识别的常用方法&#xff1a;基于模板和规则。将文本与规则进行匹配来识别出命名实体“说”、“老师”;“大学”、“医院”。优点&#xff1a;准确&#xff0c;有些实体识别只能依靠规则…

APEX开发过程中需要注意的小细节5.5

oracle保留小数点后两位的函数 在日常开发中经常用到百分比做数据对比&#xff0c;但是有可能得到的数据是一个多位小数&#xff0c;结果如下所示&#xff1a; 如果想截取部分小数如保留小数点后两位可以怎么做呢&#xff1f; 在Oracle中&#xff0c;可以使用ROUND函数来四舍…

Nature Climate Change | CO2施肥效应导致1981-2020年的全球陆地植被光合作用增加

在全球范围内&#xff0c;光合作用是大气和生物圈之间最大的单一CO2通量。因此&#xff0c;光合作用的长期变化&#xff0c;例如对大气CO2上升的响应&#xff0c;可能为气候变化提供重要的反馈。理论预测&#xff0c;CO2的增加增加了全球光合作用&#xff0c;这一过程被称为CO2…

根据 Figma 设计稿自动生成 Python GUI | 开源日报 No.221

ParthJadhav/Tkinter-Designer Stars: 8.0k License: BSD-3-Clause Tkinter-Designer 是一个用于快速创建 Python GUI 的工具&#xff0c;通过使用 Figma 设计软件&#xff0c;可以轻松地生成美观的 Tkinter GUI。 主要功能和优势包括&#xff1a; 拖放界面设计比手写代码更快…

SCI一区 | Matlab实现POA-TCN-BiGRU-Attention鹈鹕算法优化时间卷积双向门控循环单元注意力机制多变量时间序列预测

SCI一区 | Matlab实现POA-TCN-BiGRU-Attention鹈鹕算法优化时间卷积双向门控循环单元注意力机制多变量时间序列预测 目录 SCI一区 | Matlab实现POA-TCN-BiGRU-Attention鹈鹕算法优化时间卷积双向门控循环单元注意力机制多变量时间序列预测预测效果基本介绍模型描述程序设计参考…

Spring Boot 处理过滤器(filter )中抛出的异常

前言&#xff1a; 在改造老项目登录功能的时候&#xff0c;使用了过滤器对 token 进行有效性验证&#xff0c;验证通过继续进行业务请求&#xff0c;验证不通过则抛出校验异常。 过程&#xff1a; 技术方案拟定后&#xff0c;就着手开始改造&#xff0c;一切都很顺畅&#x…

OpenStack云平台实战

1、环境准备 主机CPU数量内存硬盘IPV4发行版controller48GB100GBens33: 192.168.110.27/24 esn34: 192.168.237.131/24CentOS 7.9compute48GB200GB、100GBens33: 192.168.110.26/24 esn34: 192.168.237.132/24CentOS 7.9 1.1 虚拟机安装部署 1.1.1 创建虚拟机 这里16或者17都…

机器学习——模型评价

概述 在机器学习中&#xff0c;模型评价是评估和比较不同模型性能的关键步骤之一。它是通过对模型的预测结果与真实标签进行比较&#xff0c;从而量化模型的预测能力、泛化能力和稳定性。模型评价旨在选择最佳的模型&#xff0c;理解模型的行为&#xff0c;并为模型的改进提供…

c++11 标准模板(STL)本地化库 - 平面类别 - 在字符编码间转换,包括 UTF-8、UTF-16、UTF-32 (七)

本地化库 本地环境设施包含字符分类和字符串校对、数值、货币及日期/时间格式化和分析&#xff0c;以及消息取得的国际化支持。本地环境设置控制流 I/O 、正则表达式库和 C 标准库的其他组件的行为。 平面类别 在字符编码间转换&#xff0c;包括 UTF-8、UTF-16、UTF-32 std::…

03.卸载MySQL

卸载MySQL 1.Windows卸载MySQL8 停止服务 用命令停止或者在服务中停止都可以 net stop mysql&#xff08;服务名字可以去服务里面看一下&#xff09;控制面板卸载MySQL 卸载MySQL8.0的程序可以和其他桌面应用程序一样直接在控制面板选择卸载程序&#xff0c;并在程序列表中…

nacos配置mysql(windows)

nacos默认是使用的内置数据库derby ,可通过配置修改成mysql,修改成mysql之后&#xff0c;之前配置在derby的数据会丢失 本文使用mysql版本为8.0.22 nacos版本为2.3.1 在mysql里面先创建一个数据库test(名称自定义&#xff0c;和后面配置文件里面的一样就好了) 在上面创建的数据…

【学习笔记】Python大数据处理与分析——pandas数据分析

一、pandas中的对象 1、Series对象 由两个相互关联的数组(values, index)组成&#xff0c;前者&#xff08;又称主数组&#xff09;存储数据&#xff0c;后者存储values内每个元素对应关联的标签。 import numpy as np import pandas as pds1 pd.Series([1, 3, 5, 7])print(…

数据结构排序算法

排序也称排序算法(SortAlgorithm)&#xff0c;排序是将一组数据&#xff0c;依指定的顺序进行排列的过程。 分类 内部排序【使用内存】 指将需要处理的所有数据都加载到内部存储器中进行排序插入排序 直接插入排序希尔排序 选择排序 简单选择排序堆排序 交换排序 冒泡排序快速…

【随笔】Git 高级篇 -- 远程仓库提交本地记录 git push(三十)

&#x1f48c; 所属专栏&#xff1a;【Git】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f496; 欢迎大…

大学生前端学习第一天:了解前端

引言&#xff1a; 哈喽&#xff0c;各位大学生们&#xff0c;大家好呀&#xff0c;在本篇博客&#xff0c;我们将引入一个新的板块学习&#xff0c;那就是前端&#xff0c;关于前端&#xff0c;GPT是这样描述的&#xff1a;前端通常指的是Web开发中用户界面的部分&#xff0c;…

35. UE5 RPG制作火球术技能

接下来&#xff0c;我们将制作技能了&#xff0c;总算迈进了一大步。首先回顾一下之前是如何实现技能触发的&#xff0c;然后再进入正题。 如果想实现我之前的触发方式的&#xff0c;请看此栏目的31-33篇文章&#xff0c;讲解了实现逻辑&#xff0c;这里总结一下&#xff1a; …

用于半监督的图扩散网络 笔记

1 Title Graph Neural Diffusion Networks for Semi-supervised Learning&#xff08;Wei Ye, Zexi Huang, Yunqi Hong, and Ambuj Singh&#xff09;【2022】 2 Conclusion This paper proposes a new graph neural network called GND-Nets (for Graph Neural Diffu…

1W 6KVDC 隔离双输出 DC/DC 电源模块 ——TPJ 系列

TPJ一款有超高隔离电压的电源模块&#xff0c;主要用于医疗仪器和设备&#xff0c;特别在安全设备的应用中起着相当重要的作用&#xff0c; 它的绝缘设计完全能满足对隔离电压要求超过6000V的应用&#xff0c;在额定负载1W的情况下&#xff0c;工作温度范围为–40℃到 105℃&am…