菜鸟科技网

网站搜索功能是如何实现的?

核心原理:搜索的本质是什么?

无论搜索功能多么复杂,其核心本质可以简化为以下几个步骤:

网站搜索功能是如何实现的?-图1
(图片来源网络,侵删)
  1. 数据采集:获取网站上的所有内容(文章、商品、用户信息等)。
  2. 数据处理:将采集到的非结构化文本数据(如 HTML、Markdown)进行清洗、分词、提取等操作,转换成计算机可以理解的格式。
  3. 建立索引:将处理好的数据存储到一种特殊的数据结构中,这种结构能支持快速查找,这个“数据结构”就是索引
  4. 查询处理:当用户在搜索框输入关键词时,系统对用户的查询语句进行解析和处理。
  5. 检索与匹配:根据查询语句,在索引中快速找到匹配的文档。
  6. 排序与展示:将匹配的文档按照一定的相关性规则排序,并最终以列表的形式展示给用户。

一个简单的比喻:

  • 数据采集:像把图书馆里的所有书都拿出来。
  • 数据处理:为每本书制作一张目录卡,记录书名、作者、关键词等。
  • 建立索引:把这些目录卡按照书名的拼音或笔画顺序排列好,放在一个巨大的卡片柜里。
  • 查询处理:用户说“我要找关于‘人工智能’的书”。
  • 检索与匹配:你在卡片柜里快速找到所有包含“人工智能”关键词的目录卡。
  • 排序与展示:把找到的卡片按相关性(比如销量、评分)排序,然后告诉用户“找到了以下10本书”。

三种主流的实现方案

根据网站的复杂度,主要有三种实现方案。

数据库原生搜索(适用于小型网站)

这是最简单、最直接的方式,直接利用数据库(如 MySQL, PostgreSQL)自带的 LIKE 或全文索引功能。

  • 实现方式

    网站搜索功能是如何实现的?-图2
    (图片来源网络,侵删)
    • LIKE 查询:在 SQL 语句中使用 WHERE content LIKE '%关键词%'
    • 全文索引:在数据库表上创建 FULLTEXT 索引,然后使用 MATCH() ... AGAINST(...) 语法进行查询,这种方式比 LIKE 更高效,支持分词和相关性排序。
  • 优点

    • 简单:无需额外服务,开发成本低。
    • 数据实时:数据和搜索索引在同一处,更新后立即可用。
  • 缺点

    • 性能差:当数据量达到百万级别时,查询速度会急剧下降,LIKE 查询尤其严重。
    • 功能有限:不支持复杂的搜索语法(如布尔逻辑 AND/OR/NOT)、同义词、拼写纠错、高亮等高级功能。
    • 扩展性差:难以水平扩展,无法应对高并发请求。
  • 适用场景:个人博客、小型企业官网、内容量在几万条以内的网站。

全文搜索引擎(适用于中型和大型网站)

这是目前业界最主流、最通用的方案,使用专门的搜索引擎服务,将搜索功能从业务数据库中分离出来。

网站搜索功能是如何实现的?-图3
(图片来源网络,侵删)
  • 核心组件

    • 索引器:负责从数据库或文件系统读取数据,处理并建立索引。
    • 搜索引擎:负责接收查询请求,在索引中检索,并返回结果。
    • 数据源:通常是你的业务数据库。
  • 主流工具/服务

    • Elasticsearch:目前最流行、功能最强大的开源搜索引擎,基于 Lucene 构建,分布式、高性能、功能丰富(支持复杂查询、分析、聚合等),是许多大型网站的首选。
    • Apache Solr:另一个基于 Lucene 的成熟开源搜索引擎,稳定性和企业级功能很强。
    • Algolia:一个商业化的托管搜索服务,以其极致的速度和易用性著称,你不需要管理服务器,只需上传数据即可,但成本较高。
    • Meilisearch:一个轻量级、快速且易于集成的开源搜索引擎,近年来非常受欢迎。
    • 云服务:如 AWS OpenSearchAzure Cognitive SearchGoogle Cloud Search,它们是 Elasticsearch/Solr 的云托管版本,提供了免运维、弹性扩展的便利。
  • 工作流程

    1. 数据同步:你的应用程序通过 API 或 Logstash 等工具,将数据库中的数据(如文章标题、内容、标签)实时或定时推送到 Elasticsearch。
    2. 建立索引:Elasticsearch 接收数据后,会自动进行分析(分词、建立倒排索引)。
    3. 用户查询:用户在前端输入搜索词,前端将请求发送到你的后端 API。
    4. API 查询 Elasticsearch:后端 API 将查询请求转发给 Elasticsearch。
    5. 返回结果:Elasticsearch 返回匹配结果的 ID 和摘要信息,后端 API 再根据 ID 从数据库获取完整数据,组合后返回给前端展示。
  • 优点

    • 高性能:专为搜索优化,即使面对海量数据也能快速响应。
    • 功能强大:支持模糊查询、同义词、拼写纠错、结果高亮、复杂排序、地理位置搜索等。
    • 高可用和可扩展:支持分布式部署,可以轻松水平扩展以应对高流量。
    • 与业务分离:不影响主数据库的性能。
  • 缺点

    • 架构复杂:需要额外部署和维护一个搜索引擎服务。
    • 数据一致性:需要处理数据同步的延迟问题(通常很短,但非实时)。
  • 适用场景:电商平台(商品搜索)、新闻门户(文章搜索)、论坛、知识库、任何需要强大搜索功能的中大型网站。

第三方托管搜索服务(适用于追求快速开发和稳定性的项目)

这是方案二的“开箱即用”版,你无需关心底层基础设施。

  • 代表服务:Algolia, Typesense, Pinecone (向量搜索) 等。

  • 优点

    • 开发简单:只需提供 API 密钥,通过 API 即可完成所有操作。
    • 性能卓越:服务商已经为你优化好了性能,通常响应速度极快(毫秒级)。
    • 免运维:无需安装、配置、扩展或维护任何服务器。
    • 稳定可靠:由专业团队维护,可用性高。
  • 缺点

    • 成本较高:通常按请求数、存储量和流量收费,数据量大时成本可能超过自建。
    • 定制化程度低:虽然功能强大,但可能不如自建 Elasticsearch 那样可以深度定制底层。
  • 适用场景:初创公司、项目快速上线、对开发速度和稳定性要求高于成本控制的项目。


实现步骤详解(以 Elasticsearch 为例)

假设我们选择方案二,使用 Elasticsearch 来实现一个博客的搜索功能。

步骤 1:需求分析

  • 搜索什么?、内容、作者、标签。
  • 如何排序?:默认按相关性(包含关键词的次数、位置等),也可以按发布时间倒序。
  • 需要哪些功能?:关键词高亮、分页。

步骤 2:技术选型

  • 后端:Node.js (Express) / Python (Django/Flask) / Java (Spring Boot) 等。
  • 搜索引擎:Elasticsearch。
  • 数据库:MySQL / PostgreSQL (存储文章的完整数据)。
  • 前端:React / Vue / 原生 HTML + JS。

步骤 3:环境搭建

  1. 安装并运行 Elasticsearch(可以使用 Docker 快速启动)。
  2. 创建后端项目,并安装 Elasticsearch 的官方客户端库(如 @elastic/elasticsearch for Node.js)。

步骤 4:数据同步(建立索引)

  1. 创建索引:在 Elasticsearch 中创建一个名为 articles 的索引,并定义其映射(Mapping),即字段类型。
    // PUT /articles
    {
      "mappings": {
        "properties": {
          "title": { "type": "text" },
          "content": { "type": "text" },
          "author": { "type": "keyword" }, // keyword 类型不进行分词,用于精确匹配
          "publish_date": { "type": "date" },
          "tags": { "type": "keyword" }
        }
      }
    }
  2. 同步数据:编写一个脚本或使用 Logstash,定期从你的 MySQL 数据库中读取所有文章数据,然后通过 Elasticsearch 的 API (_bulk) 批量写入到 articles 索引中。

步骤 5:实现后端 API

创建一个 API 端点,/api/search

  • 接收请求:API 接收来自前端的查询参数,如 q (查询词)、page (页码)、size (每页数量)。

  • 构建查询:使用 Elasticsearch 的查询语法(Query DSL)来构建查询语句。

    // Node.js @elastic/elasticsearch 示例
    const { Client } = require('@elastic/elasticsearch');
    const client = new Client({ node: 'http://localhost:9200' });
    async function searchArticles(query, page = 1, size = 10) {
      const response = await client.search({
        index: 'articles',
        body: {
          query: {
            multi_match: {
              query: query,
              fields: ['title^3', 'content', 'tags'], // title 权重更高
            }
          },
          highlight: {
            fields: {
              content: { fragment_size: 150 }
            }
          },
          from: (page - 1) * size,
          size: size,
          sort: [{ publish_date: { order: 'desc' } }]
        }
      });
      return response.body;
    }
  • 返回结果:将 Elasticsearch 返回的结果进行格式化,返回给前端,结果应包含文章 ID、标题、高亮内容)等。

步骤 6:实现前端界面

  1. 搜索框:一个 input 标签,用户输入关键词。
  2. 搜索按钮:触发搜索请求。
  3. 结果展示区:一个列表,用于展示搜索结果。
  4. JavaScript 逻辑
    • 监听搜索框的提交事件。
    • 获取用户输入的关键词。
    • 使用 fetchaxios 调用后端的 /api/search 接口。
    • 接收到数据后,动态渲染结果列表,并显示高亮内容。

高级搜索功能

基础搜索完成后,还可以根据需求添加高级功能,这些在 Elasticsearch 中都很容易实现:

  • 模糊搜索:当用户拼写错误时,也能找到相关结果。
  • 同义词搜索:搜索 "电脑" 时,也能搜到 "计算机"。
  • 自动补全:用户输入时,下拉提示可能的关键词。
  • 拼写纠错:在搜索结果页提示“您是不是要搜索...”。
  • 过滤与排序:按分类、价格、时间范围等进行筛选和排序。
  • 向量搜索:用于实现语义搜索,即搜索“猫”能找到关于“老虎”的内容,因为它们语义相关。
方案 优点 缺点 适用场景
数据库原生搜索 简单、成本低、数据实时 性能差、功能有限、扩展性差 小型网站、个人博客
全文搜索引擎 高性能、功能强大、可扩展、架构清晰 架构复杂、需要额外维护 中大型网站、电商平台、内容门户
第三方托管服务 开发快、免运维、性能卓越 成本较高、定制化程度低 快速上线项目、初创公司

对于绝大多数现代网站,方案二(全文搜索引擎) 是最佳实践,它提供了强大的功能和足够的灵活性,能够满足网站长期发展的需求,如果你的项目追求极致的开发速度和稳定性,方案三(第三方托管服务) 是一个非常好的选择。

分享:
扫描分享到社交APP
上一篇
下一篇