# 搜索功能 **本文引用的文件** - [search.controller.ts](file://server/src/modules/search/search.controller.ts) - [search.service.ts](file://server/src/modules/search/search.service.ts) - [cache.ts](file://server/src/middleware/cache.ts) - [security.ts](file://server/src/middleware/security.ts) - [redis.service.ts](file://server/src/services/redis.service.ts) - [schema.prisma](file://server/prisma/schema.prisma) - [index.vue](file://my-uniapp-vue3/src/pages/search/index.vue) - [API.md](file://docs/API.md) ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖关系分析](#依赖关系分析) 7. [性能考虑](#性能考虑) 8. [故障排查指南](#故障排查指南) 9. [结论](#结论) 10. [附录](#附录) ## 简介 本文件面向“搜索功能”的技术实现与运维优化,覆盖以下主题: - 全文搜索实现与关键词匹配策略 - 搜索结果排序与相关性评分(当前实现为基于字段包含与时间倒序) - 搜索索引构建、搜索引擎集成现状与扩展建议 - 缓存策略与性能优化 - 搜索历史记录、热门搜索词统计与搜索建议生成 - 多维度过滤、地理位置筛选、时间范围限制的扩展路径 - 搜索 API 接口规范、参数与返回格式 - 性能优化、查询语句优化、索引维护策略 - 个性化推荐、A/B 测试与用户体验优化建议 - 安全防护、恶意查询过滤与搜索统计分析 ## 项目结构 搜索功能由前端页面、后端控制器与服务层、数据库模型以及缓存与安全中间件共同组成。整体采用前后端分离架构,前端通过 HTTP 接口调用后端搜索能力。 ```mermaid graph TB FE["前端页面
search/index.vue"] --> API["后端接口
search.controller.ts"] API --> SVC["搜索服务
search.service.ts"] SVC --> PRISMA["数据库模型
schema.prisma"] API --> CACHE["缓存中间件
cache.ts"] API --> SEC["安全中间件
security.ts"] CACHE --> REDIS["Redis 缓存
redis.service.ts"] ``` **图表来源** - [search.controller.ts:1-170](file://server/src/modules/search/search.controller.ts#L1-L170) - [search.service.ts:1-145](file://server/src/modules/search/search.service.ts#L1-L145) - [schema.prisma:220-240](file://server/prisma/schema.prisma#L220-L240) - [cache.ts:1-98](file://server/src/middleware/cache.ts#L1-L98) - [security.ts:1-154](file://server/src/middleware/security.ts#L1-L154) - [redis.service.ts:1-274](file://server/src/services/redis.service.ts#L1-L274) - [index.vue:1-468](file://my-uniapp-vue3/src/pages/search/index.vue#L1-L468) **章节来源** - [search.controller.ts:1-170](file://server/src/modules/search/search.controller.ts#L1-L170) - [search.service.ts:1-145](file://server/src/modules/search/search.service.ts#L1-L145) - [schema.prisma:220-240](file://server/prisma/schema.prisma#L220-L240) - [cache.ts:1-98](file://server/src/middleware/cache.ts#L1-L98) - [security.ts:1-154](file://server/src/middleware/security.ts#L1-L154) - [redis.service.ts:1-274](file://server/src/services/redis.service.ts#L1-L274) - [index.vue:1-468](file://my-uniapp-vue3/src/pages/search/index.vue#L1-L468) ## 核心组件 - 前端搜索页面:负责输入、高亮显示、历史与热门展示、调用后端接口。 - 后端控制器:定义搜索、热门、历史等接口,参数校验与错误处理。 - 搜索服务:封装数据库查询逻辑,维护热门词与历史记录。 - 数据库模型:定义搜索历史与热门搜索词表结构及索引。 - 缓存中间件:提供通用缓存能力,可按需对搜索接口进行缓存。 - 安全中间件:提供 XSS 与 SQL 注入防护,敏感数据脱敏。 - Redis 服务:提供连接、读写、批量删除等操作,支撑缓存中间件。 **章节来源** - [index.vue:166-250](file://my-uniapp-vue3/src/pages/search/index.vue#L166-L250) - [search.controller.ts:10-167](file://server/src/modules/search/search.controller.ts#L10-L167) - [search.service.ts:13-140](file://server/src/modules/search/search.service.ts#L13-L140) - [schema.prisma:220-240](file://server/prisma/schema.prisma#L220-L240) - [cache.ts:13-97](file://server/src/middleware/cache.ts#L13-L97) - [security.ts:7-153](file://server/src/middleware/security.ts#L7-L153) - [redis.service.ts:43-149](file://server/src/services/redis.service.ts#L43-L149) ## 架构总览 下图展示了从前端到后端、再到数据库与缓存的整体交互流程。 ```mermaid sequenceDiagram participant U as "用户" participant FE as "前端页面
search/index.vue" participant CTRL as "控制器
search.controller.ts" participant SVC as "服务层
search.service.ts" participant DB as "数据库
Prisma" participant R as "缓存中间件
cache.ts" participant RS as "Redis
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](file://my-uniapp-vue3/src/pages/search/index.vue#L224-L250) - [search.controller.ts:10-36](file://server/src/modules/search/search.controller.ts#L10-L36) - [search.service.ts:13-35](file://server/src/modules/search/search.service.ts#L13-L35) - [cache.ts:13-47](file://server/src/middleware/cache.ts#L13-L47) - [redis.service.ts:52-82](file://server/src/services/redis.service.ts#L52-L82) ## 详细组件分析 ### 前端搜索页面(search/index.vue) - 功能要点 - 搜索栏输入与确认事件绑定 - 高亮关键词显示 - 搜索历史与热门推荐展示 - 调用后端接口:获取历史、热门、执行搜索、保存历史 - 本地缓存热门词,提升离线体验 - 关键流程 - 初始化加载历史与热门 - 用户点击历史或热门词触发搜索 - 搜索成功后刷新历史与热门,并更新本地缓存 ```mermaid flowchart TD Start(["进入搜索页"]) --> LoadCtx["加载搜索上下文
历史 + 热门"] LoadCtx --> Input["输入关键词"] Input --> Submit{"是否为空?"} Submit --> |是| Wait["等待输入"] Submit --> |否| SaveHist["保存搜索历史"] SaveHist --> CallAPI["调用 /api/search?q=&limit="] CallAPI --> Render["渲染结果/高亮关键词"] Render --> Refresh["刷新历史与热门"] Refresh --> End(["结束"]) ``` **图表来源** - [index.vue:166-250](file://my-uniapp-vue3/src/pages/search/index.vue#L166-L250) **章节来源** - [index.vue:1-468](file://my-uniapp-vue3/src/pages/search/index.vue#L1-L468) ### 后端控制器(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 - 错误处理:捕获异常并返回友好提示 ```mermaid 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](file://server/src/modules/search/search.controller.ts#L10-L36) **章节来源** - [search.controller.ts:1-170](file://server/src/modules/search/search.controller.ts#L1-L170) ### 搜索服务(search.service.ts) - 搜索逻辑 - 去除多余空白,构造查询条件(标题/描述包含关键词) - 按创建时间倒序排序,限制返回数量 - 热门搜索词 - 查询热门词表,按 sort 与 count 倒序排序 - 历史记录 - 获取用户历史,去重并按时间倒序 - 保存历史时先删同用户同关键词旧记录,再插入新记录 - 控制每用户最多 20 条历史 - 同步更新热门词计数(存在则自增,否则新建) ```mermaid flowchart TD S1["输入: query, limit"] --> Trim["去除空白"] Trim --> Empty{"是否为空?"} Empty --> |是| ReturnEmpty["返回空数组"] Empty --> |否| Build["构造查询条件
标题/描述包含"] Build --> Order["按创建时间倒序"] Order --> Take["限制数量"] Take --> Exec["执行查询"] Exec --> Out["返回结果"] ``` **图表来源** - [search.service.ts:13-35](file://server/src/modules/search/search.service.ts#L13-L35) **章节来源** - [search.service.ts:1-145](file://server/src/modules/search/search.service.ts#L1-L145) ### 数据库模型(schema.prisma) - 搜索相关模型 - SearchHistory:用户搜索历史 - HotSearch:热门搜索词(keyword、count、sort、时间索引) - 索引设计 - SearchHistory:复合索引(userId, createdAt)、userId 单列索引 - HotSearch:sort、count 单列索引 - 与业务关联 - 服务层通过 Prisma 对上述模型进行 CRUD ```mermaid 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](file://server/prisma/schema.prisma#L130-L159) - [schema.prisma:220-240](file://server/prisma/schema.prisma#L220-L240) **章节来源** - [schema.prisma:220-240](file://server/prisma/schema.prisma#L220-L240) ### 缓存中间件(cache.ts)与 Redis 服务(redis.service.ts) - 缓存中间件 - 可配置 TTL、键前缀、自定义键生成器 - 命中则直接返回缓存;未命中执行请求并将成功响应写入缓存 - Redis 不可用时自动降级跳过缓存 - Redis 服务 - 提供 get/set/getJSON/setJSON/del/delPattern 等常用操作 - 连接状态管理与错误日志 ```mermaid 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](file://server/src/middleware/cache.ts#L13-L97) - [redis.service.ts:43-149](file://server/src/services/redis.service.ts#L43-L149) **章节来源** - [cache.ts:1-98](file://server/src/middleware/cache.ts#L1-L98) - [redis.service.ts:1-274](file://server/src/services/redis.service.ts#L1-L274) ### 安全中间件(security.ts) - XSS 防护:递归清理请求体与查询参数中的危险字符 - SQL 注入防护:检测常见注入模式并拒绝非法请求 - 敏感数据脱敏:对响应中的敏感字段进行掩码处理 ```mermaid flowchart TD In["接收请求"] --> XSS["XSS 过滤"] XSS --> SQL["SQL 注入检测"] SQL --> OK{"合法?"} OK --> |否| Block["返回 400"] OK --> |是| Next["继续后续处理"] ``` **图表来源** - [security.ts:7-102](file://server/src/middleware/security.ts#L7-L102) **章节来源** - [security.ts:1-154](file://server/src/middleware/security.ts#L1-L154) ## 依赖关系分析 - 前端依赖后端接口,后端依赖服务层,服务层依赖 Prisma 模型 - 控制器与服务层之间为清晰的职责边界 - 缓存中间件与安全中间件作为横切关注点,可按需组合使用 - Redis 服务为缓存中间件提供基础设施 ```mermaid graph LR FE["前端"] --> CTRL["控制器"] CTRL --> SVC["服务层"] SVC --> PRISMA["Prisma 模型"] CTRL --> CACHE["缓存中间件"] CTRL --> SEC["安全中间件"] CACHE --> REDIS["Redis 服务"] ``` **图表来源** - [search.controller.ts:1-170](file://server/src/modules/search/search.controller.ts#L1-L170) - [search.service.ts:1-145](file://server/src/modules/search/search.service.ts#L1-L145) - [cache.ts:1-98](file://server/src/middleware/cache.ts#L1-L98) - [security.ts:1-154](file://server/src/middleware/security.ts#L1-L154) - [redis.service.ts:1-274](file://server/src/services/redis.service.ts#L1-L274) **章节来源** - [search.controller.ts:1-170](file://server/src/modules/search/search.controller.ts#L1-L170) - [search.service.ts:1-145](file://server/src/modules/search/search.service.ts#L1-L145) - [cache.ts:1-98](file://server/src/middleware/cache.ts#L1-L98) - [security.ts:1-154](file://server/src/middleware/security.ts#L1-L154) - [redis.service.ts:1-274](file://server/src/services/redis.service.ts#L1-L274) ## 性能考虑 - 当前实现 - 搜索使用“包含”匹配,排序按创建时间倒序,未引入全文索引或相关性评分 - 未对搜索接口启用缓存中间件 - 优化建议 - 引入全文搜索引擎(如 Elasticsearch/Meilisearch)替代简单包含匹配,支持分词、近似匹配、权重排序 - 在控制器层对高频搜索接口增加缓存中间件,合理设置 TTL - 对热门词与历史接口也启用缓存,降低数据库压力 - 使用数据库索引优化:在标题/描述字段建立全文索引或联合索引 - 对搜索服务的查询进行 LIMIT 控制与超时保护 - 前端对频繁输入进行防抖,减少无效请求 - 对热门词统计与历史上限控制,避免数据膨胀 [本节为通用性能指导,不直接分析具体文件] ## 故障排查指南 - 搜索无结果 - 检查关键词是否为空或仅空白字符 - 确认数据库中是否存在匹配的书籍标题/描述 - 接口报错 - 查看控制器错误处理返回的 message - 检查安全中间件是否拦截了非法字符或注入尝试 - 缓存问题 - 确认 Redis 连接状态与可用性 - 检查缓存键前缀与 TTL 设置 - 历史与热门异常 - 检查服务层保存历史时的去重与上限逻辑 - 确认热门词计数更新是否成功 **章节来源** - [search.controller.ts:30-35](file://server/src/modules/search/search.controller.ts#L30-L35) - [security.ts:61-102](file://server/src/middleware/security.ts#L61-L102) - [redis.service.ts:43-45](file://server/src/services/redis.service.ts#L43-L45) - [search.service.ts:72-119](file://server/src/modules/search/search.service.ts#L72-L119) ## 结论 当前搜索功能实现了基础的关键词匹配、历史与热门统计,具备良好的扩展空间。建议下一步引入全文搜索引擎与缓存中间件,完善相关性评分与多维过滤能力,并加强安全与性能优化,以满足更复杂的搜索场景与更高的并发需求。 [本节为总结性内容,不直接分析具体文件] ## 附录 ### 搜索 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](file://server/src/modules/search/search.controller.ts#L10-L167) - [API.md:488-498](file://docs/API.md#L488-L498) ### 搜索相关性与排序建议 - 当前排序:按创建时间倒序 - 建议排序因子: - 文档字段权重(标题、描述) - 热度/历史搜索计数 - 用户偏好与历史行为 - 时间衰减因子 - 实现方式: - 引入全文搜索引擎,支持 TF-IDF、BM25 等评分 - 在服务层计算加权分数并排序 [本节为概念性建议,不直接分析具体文件] ### 多维度过滤与扩展路径 - 已有字段 - 标题、描述(包含匹配) - 建议新增 - 类别/风格/受众等分类过滤 - 时长/字数范围限制 - 发布时间范围 - 地理位置(若适用) - 实施步骤 - 在数据库模型中添加相应字段与索引 - 在控制器与服务层扩展查询条件 - 在前端提供过滤控件与持久化 [本节为概念性建议,不直接分析具体文件] ### 缓存策略与安全强化 - 缓存策略 - 对 /api/search、/api/search/hot、/api/search/history 启用缓存中间件 - 合理设置 TTL(如热门词 5 分钟,搜索结果 1 分钟) - 使用键前缀区分不同接口与用户 - 安全强化 - 在控制器层启用安全中间件 - 对用户输入进行严格白名单与长度限制 - 对高频接口增加限流与黑名单机制 **章节来源** - [cache.ts:13-97](file://server/src/middleware/cache.ts#L13-L97) - [security.ts:7-153](file://server/src/middleware/security.ts#L7-L153)