搜索功能.md 17 KB

搜索功能

本文引用的文件

  • search.controller.ts
  • search.service.ts
  • cache.ts
  • security.ts
  • redis.service.ts
  • schema.prisma
  • index.vue
  • API.md

目录

  1. 简介
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖关系分析
  7. 性能考虑
  8. 故障排查指南
  9. 结论
  10. 附录

简介

本文件面向“搜索功能”的技术实现与运维优化,覆盖以下主题:

  • 全文搜索实现与关键词匹配策略
  • 搜索结果排序与相关性评分(当前实现为基于字段包含与时间倒序)
  • 搜索索引构建、搜索引擎集成现状与扩展建议
  • 缓存策略与性能优化
  • 搜索历史记录、热门搜索词统计与搜索建议生成
  • 多维度过滤、地理位置筛选、时间范围限制的扩展路径
  • 搜索 API 接口规范、参数与返回格式
  • 性能优化、查询语句优化、索引维护策略
  • 个性化推荐、A/B 测试与用户体验优化建议
  • 安全防护、恶意查询过滤与搜索统计分析

项目结构

搜索功能由前端页面、后端控制器与服务层、数据库模型以及缓存与安全中间件共同组成。整体采用前后端分离架构,前端通过 HTTP 接口调用后端搜索能力。

graph TB
FE["前端页面<br/>search/index.vue"] --> API["后端接口<br/>search.controller.ts"]
API --> SVC["搜索服务<br/>search.service.ts"]
SVC --> PRISMA["数据库模型<br/>schema.prisma"]
API --> CACHE["缓存中间件<br/>cache.ts"]
API --> SEC["安全中间件<br/>security.ts"]
CACHE --> REDIS["Redis 缓存<br/>redis.service.ts"]

图表来源

  • search.controller.ts:1-170
  • search.service.ts:1-145
  • schema.prisma:220-240
  • cache.ts:1-98
  • security.ts:1-154
  • redis.service.ts:1-274
  • index.vue:1-468

章节来源

  • search.controller.ts:1-170
  • search.service.ts:1-145
  • schema.prisma:220-240
  • cache.ts:1-98
  • security.ts:1-154
  • redis.service.ts:1-274
  • index.vue:1-468

核心组件

  • 前端搜索页面:负责输入、高亮显示、历史与热门展示、调用后端接口。
  • 后端控制器:定义搜索、热门、历史等接口,参数校验与错误处理。
  • 搜索服务:封装数据库查询逻辑,维护热门词与历史记录。
  • 数据库模型:定义搜索历史与热门搜索词表结构及索引。
  • 缓存中间件:提供通用缓存能力,可按需对搜索接口进行缓存。
  • 安全中间件:提供 XSS 与 SQL 注入防护,敏感数据脱敏。
  • Redis 服务:提供连接、读写、批量删除等操作,支撑缓存中间件。

章节来源

  • index.vue:166-250
  • search.controller.ts:10-167
  • search.service.ts:13-140
  • schema.prisma:220-240
  • cache.ts:13-97
  • security.ts:7-153
  • redis.service.ts:43-149

架构总览

下图展示了从前端到后端、再到数据库与缓存的整体交互流程。

sequenceDiagram
participant U as "用户"
participant FE as "前端页面<br/>search/index.vue"
participant CTRL as "控制器<br/>search.controller.ts"
participant SVC as "服务层<br/>search.service.ts"
participant DB as "数据库<br/>Prisma"
participant R as "缓存中间件<br/>cache.ts"
participant RS as "Redis<br/>redis.service.ts"
U->>FE : 输入关键词并提交
FE->>CTRL : GET /api/search?q=关键词&limit=N
R-->>CTRL : 命中缓存? 否则透传
CTRL->>SVC : searchAudio(query, limit)
SVC->>DB : 查询书籍标题/描述包含关键词
DB-->>SVC : 返回结果集
SVC-->>CTRL : 结果数组
CTRL-->>FE : 统一响应格式
R-->>RS : 写入缓存(可选)

图表来源

  • index.vue:224-250
  • search.controller.ts:10-36
  • search.service.ts:13-35
  • cache.ts:13-47
  • redis.service.ts:52-82

详细组件分析

前端搜索页面(search/index.vue)

  • 功能要点
    • 搜索栏输入与确认事件绑定
    • 高亮关键词显示
    • 搜索历史与热门推荐展示
    • 调用后端接口:获取历史、热门、执行搜索、保存历史
    • 本地缓存热门词,提升离线体验
  • 关键流程

    • 初始化加载历史与热门
    • 用户点击历史或热门词触发搜索
    • 搜索成功后刷新历史与热门,并更新本地缓存

      flowchart TD
      Start(["进入搜索页"]) --> LoadCtx["加载搜索上下文<br/>历史 + 热门"]
      LoadCtx --> Input["输入关键词"]
      Input --> Submit{"是否为空?"}
      Submit --> |是| Wait["等待输入"]
      Submit --> |否| SaveHist["保存搜索历史"]
      SaveHist --> CallAPI["调用 /api/search?q=&limit="]
      CallAPI --> Render["渲染结果/高亮关键词"]
      Render --> Refresh["刷新历史与热门"]
      Refresh --> End(["结束"])
      

图表来源

  • index.vue:166-250

章节来源

  • index.vue:1-468

后端控制器(search.controller.ts)

  • 接口定义
    • GET /api/search:全文搜索(关键词、结果数量限制)
    • GET /api/search/hot:热门搜索词
    • GET /api/search/history:用户搜索历史
    • POST /api/search/history:保存搜索历史
    • DELETE /api/search/history:删除单条历史
    • DELETE /api/search/history/all:清空历史
  • 参数与返回

    • 统一响应格式:code、message、data
    • 错误处理:捕获异常并返回友好提示

      sequenceDiagram
      participant FE as "前端"
      participant CTRL as "控制器"
      participant SVC as "服务层"
      FE->>CTRL : GET /api/search?q=...&limit=...
      CTRL->>CTRL : 参数校验
      CTRL->>SVC : searchAudio(query, limit)
      SVC-->>CTRL : 结果数组
      CTRL-->>FE : {code,message,data}
      

图表来源

  • search.controller.ts:10-36

章节来源

  • search.controller.ts:1-170

搜索服务(search.service.ts)

  • 搜索逻辑
    • 去除多余空白,构造查询条件(标题/描述包含关键词)
    • 按创建时间倒序排序,限制返回数量
  • 热门搜索词
    • 查询热门词表,按 sort 与 count 倒序排序
  • 历史记录

    • 获取用户历史,去重并按时间倒序
    • 保存历史时先删同用户同关键词旧记录,再插入新记录
    • 控制每用户最多 20 条历史
    • 同步更新热门词计数(存在则自增,否则新建)

      flowchart TD
      S1["输入: query, limit"] --> Trim["去除空白"]
      Trim --> Empty{"是否为空?"}
      Empty --> |是| ReturnEmpty["返回空数组"]
      Empty --> |否| Build["构造查询条件<br/>标题/描述包含"]
      Build --> Order["按创建时间倒序"]
      Order --> Take["限制数量"]
      Take --> Exec["执行查询"]
      Exec --> Out["返回结果"]
      

图表来源

  • search.service.ts:13-35

章节来源

  • search.service.ts:1-145

数据库模型(schema.prisma)

  • 搜索相关模型
    • SearchHistory:用户搜索历史
    • HotSearch:热门搜索词(keyword、count、sort、时间索引)
  • 索引设计
    • SearchHistory:复合索引(userId, createdAt)、userId 单列索引
    • HotSearch:sort、count 单列索引
  • 与业务关联

    • 服务层通过 Prisma 对上述模型进行 CRUD

      erDiagram
      USER {
      int id PK
      string phone
      string openid
      }
      BOOK {
      int id PK
      string title
      text description
      datetime createdAt
      }
      SEARCH_HISTORY {
      int id PK
      int userId
      string keyword
      datetime createdAt
      }
      HOT_SEARCH {
      int id PK
      string keyword
      int count
      int sort
      datetime createdAt
      datetime updatedAt
      }
      USER ||--o{ SEARCH_HISTORY : "拥有"
      BOOK ||--o{ SEARCH_HISTORY : "被搜索"
      

图表来源

  • schema.prisma:130-159
  • schema.prisma:220-240

章节来源

  • schema.prisma:220-240

缓存中间件(cache.ts)与 Redis 服务(redis.service.ts)

  • 缓存中间件
    • 可配置 TTL、键前缀、自定义键生成器
    • 命中则直接返回缓存;未命中执行请求并将成功响应写入缓存
    • Redis 不可用时自动降级跳过缓存
  • Redis 服务

    • 提供 get/set/getJSON/setJSON/del/delPattern 等常用操作
    • 连接状态管理与错误日志

      classDiagram
      class CacheMiddleware {
      +createCache(options)
      +clearCache(keyPrefix)
      }
      class RedisService {
      +isAvailable() bool
      +get(key) string
      +set(key,value,ttl) bool
      +getJSON(key) any
      +setJSON(key,obj,ttl) bool
      +del(key) bool
      +delPattern(pattern) bool
      }
      CacheMiddleware --> RedisService : "使用"
      

图表来源

  • cache.ts:13-97
  • redis.service.ts:43-149

章节来源

  • cache.ts:1-98
  • redis.service.ts:1-274

安全中间件(security.ts)

  • XSS 防护:递归清理请求体与查询参数中的危险字符
  • SQL 注入防护:检测常见注入模式并拒绝非法请求
  • 敏感数据脱敏:对响应中的敏感字段进行掩码处理

    flowchart TD
    In["接收请求"] --> XSS["XSS 过滤"]
    XSS --> SQL["SQL 注入检测"]
    SQL --> OK{"合法?"}
    OK --> |否| Block["返回 400"]
    OK --> |是| Next["继续后续处理"]
    

图表来源

  • security.ts:7-102

章节来源

  • security.ts:1-154

依赖关系分析

  • 前端依赖后端接口,后端依赖服务层,服务层依赖 Prisma 模型
  • 控制器与服务层之间为清晰的职责边界
  • 缓存中间件与安全中间件作为横切关注点,可按需组合使用
  • Redis 服务为缓存中间件提供基础设施

    graph LR
    FE["前端"] --> CTRL["控制器"]
    CTRL --> SVC["服务层"]
    SVC --> PRISMA["Prisma 模型"]
    CTRL --> CACHE["缓存中间件"]
    CTRL --> SEC["安全中间件"]
    CACHE --> REDIS["Redis 服务"]
    

图表来源

  • search.controller.ts:1-170
  • search.service.ts:1-145
  • cache.ts:1-98
  • security.ts:1-154
  • redis.service.ts:1-274

章节来源

  • search.controller.ts:1-170
  • search.service.ts:1-145
  • cache.ts:1-98
  • security.ts:1-154
  • redis.service.ts:1-274

性能考虑

  • 当前实现
    • 搜索使用“包含”匹配,排序按创建时间倒序,未引入全文索引或相关性评分
    • 未对搜索接口启用缓存中间件
  • 优化建议
    • 引入全文搜索引擎(如 Elasticsearch/Meilisearch)替代简单包含匹配,支持分词、近似匹配、权重排序
    • 在控制器层对高频搜索接口增加缓存中间件,合理设置 TTL
    • 对热门词与历史接口也启用缓存,降低数据库压力
    • 使用数据库索引优化:在标题/描述字段建立全文索引或联合索引
    • 对搜索服务的查询进行 LIMIT 控制与超时保护
    • 前端对频繁输入进行防抖,减少无效请求
    • 对热门词统计与历史上限控制,避免数据膨胀

[本节为通用性能指导,不直接分析具体文件]

故障排查指南

  • 搜索无结果
    • 检查关键词是否为空或仅空白字符
    • 确认数据库中是否存在匹配的书籍标题/描述
  • 接口报错
    • 查看控制器错误处理返回的 message
    • 检查安全中间件是否拦截了非法字符或注入尝试
  • 缓存问题
    • 确认 Redis 连接状态与可用性
    • 检查缓存键前缀与 TTL 设置
  • 历史与热门异常
    • 检查服务层保存历史时的去重与上限逻辑
    • 确认热门词计数更新是否成功

章节来源

  • search.controller.ts:30-35
  • security.ts:61-102
  • redis.service.ts:43-45
  • search.service.ts:72-119

结论

当前搜索功能实现了基础的关键词匹配、历史与热门统计,具备良好的扩展空间。建议下一步引入全文搜索引擎与缓存中间件,完善相关性评分与多维过滤能力,并加强安全与性能优化,以满足更复杂的搜索场景与更高的并发需求。

[本节为总结性内容,不直接分析具体文件]

附录

搜索 API 接口文档

  • 搜索音频
    • 方法与路径:GET /api/search
    • 查询参数:
    • q:关键词(必填)
    • limit:结果数量限制(默认 20)
    • 返回:统一响应格式,data 为结果数组
  • 获取热门搜索词
    • 方法与路径:GET /api/search/hot
    • 查询参数:
    • limit:返回数量限制(默认 10)
    • 返回:统一响应格式,data 为热门词数组
  • 获取搜索历史
    • 方法与路径:GET /api/search/history
    • 查询参数:
    • userId:用户 ID(必填)
    • limit:返回数量限制(默认 5)
    • 返回:统一响应格式,data 为历史数组
  • 保存搜索历史
    • 方法与路径:POST /api/search/history
    • 请求体:
    • userId:用户 ID
    • keyword:关键词(必填)
    • 返回:统一响应格式
  • 删除单条搜索历史
    • 方法与路径:DELETE /api/search/history
    • 查询参数:
    • userId:用户 ID
    • keyword:关键词(必填)
    • 返回:统一响应格式
  • 清空搜索历史
    • 方法与路径:DELETE /api/search/history/all
    • 查询参数:
    • userId:用户 ID(必填)
    • 返回:统一响应格式

章节来源

  • search.controller.ts:10-167
  • API.md:488-498

搜索相关性与排序建议

  • 当前排序:按创建时间倒序
  • 建议排序因子:
    • 文档字段权重(标题、描述)
    • 热度/历史搜索计数
    • 用户偏好与历史行为
    • 时间衰减因子
  • 实现方式:
    • 引入全文搜索引擎,支持 TF-IDF、BM25 等评分
    • 在服务层计算加权分数并排序

[本节为概念性建议,不直接分析具体文件]

多维度过滤与扩展路径

  • 已有字段
    • 标题、描述(包含匹配)
  • 建议新增
    • 类别/风格/受众等分类过滤
    • 时长/字数范围限制
    • 发布时间范围
    • 地理位置(若适用)
  • 实施步骤
    • 在数据库模型中添加相应字段与索引
    • 在控制器与服务层扩展查询条件
    • 在前端提供过滤控件与持久化

[本节为概念性建议,不直接分析具体文件]

缓存策略与安全强化

  • 缓存策略
    • 对 /api/search、/api/search/hot、/api/search/history 启用缓存中间件
    • 合理设置 TTL(如热门词 5 分钟,搜索结果 1 分钟)
    • 使用键前缀区分不同接口与用户
  • 安全强化
    • 在控制器层启用安全中间件
    • 对用户输入进行严格白名单与长度限制
    • 对高频接口增加限流与黑名单机制

章节来源

  • cache.ts:13-97
  • security.ts:7-153