355 lines
16 KiB
Markdown
355 lines
16 KiB
Markdown
# 搜索引擎
|
||
|
||
<cite>
|
||
**本文引用的文件**
|
||
- [internal/search/meilisearch.go](file://internal/search/meilisearch.go)
|
||
- [internal/config/meilisearch.go](file://internal/config/meilisearch.go)
|
||
- [internal/config/config.go](file://internal/config/config.go)
|
||
- [cmd/server/main.go](file://cmd/server/main.go)
|
||
- [internal/router/router.go](file://internal/router/router.go)
|
||
- [internal/handler/model_list.go](file://internal/handler/model_list.go)
|
||
- [internal/handler/model.go](file://internal/handler/model.go)
|
||
- [internal/repository/model.go](file://internal/repository/model.go)
|
||
- [internal/model/model.go](file://internal/model/model.go)
|
||
- [internal/database/mysql.go](file://internal/database/mysql.go)
|
||
- [internal/cache/redis.go](file://internal/cache/redis.go)
|
||
- [internal/response/response.go](file://internal/response/response.go)
|
||
- [README.md](file://README.md)
|
||
</cite>
|
||
|
||
## 目录
|
||
1. [简介](#简介)
|
||
2. [项目结构](#项目结构)
|
||
3. [核心组件](#核心组件)
|
||
4. [架构总览](#架构总览)
|
||
5. [详细组件分析](#详细组件分析)
|
||
6. [依赖关系分析](#依赖关系分析)
|
||
7. [性能考虑](#性能考虑)
|
||
8. [故障排除指南](#故障排除指南)
|
||
9. [结论](#结论)
|
||
10. [附录](#附录)
|
||
|
||
## 简介
|
||
本文件面向 Luxsin 应用 API 项目中的搜索引擎集成,系统性介绍 Meilisearch 的配置与初始化、搜索客户端的创建流程、索引管理策略、全文搜索实现原理以及搜索 API 的使用示例。同时提供性能优化建议、高亮显示、自动补全与相关性排序的扩展思路,以及连接问题诊断、索引重建与性能调优的故障排除指南。内容从基础概念到高级应用,兼顾不同层次开发者需求。
|
||
|
||
## 项目结构
|
||
该项目采用分层架构,围绕 Gin HTTP 框架组织模块:
|
||
- 配置层:集中加载运行环境、数据库、Meilisearch、Redis 等配置
|
||
- 数据访问层:MySQL 数据库连接与模型扫描
|
||
- 搜索层:Meilisearch 客户端与搜索请求封装
|
||
- 处理层:HTTP 处理器与路由注册
|
||
- 缓存层:Redis 客户端(用于查询缓存等)
|
||
- 工具层:统一响应体、日志、编码工具
|
||
|
||
```mermaid
|
||
graph TB
|
||
subgraph "应用入口"
|
||
MAIN["cmd/server/main.go"]
|
||
end
|
||
subgraph "配置层"
|
||
CFG["internal/config/config.go"]
|
||
MS_CFG["internal/config/meilisearch.go"]
|
||
end
|
||
subgraph "数据访问层"
|
||
MYSQL["internal/database/mysql.go"]
|
||
REPO["internal/repository/model.go"]
|
||
MODEL["internal/model/model.go"]
|
||
end
|
||
subgraph "搜索层"
|
||
SEARCH_CLIENT["internal/search/meilisearch.go"]
|
||
end
|
||
subgraph "处理层"
|
||
ROUTER["internal/router/router.go"]
|
||
HANDLER_MODEL["internal/handler/model.go"]
|
||
HANDLER_MODEL_LIST["internal/handler/model_list.go"]
|
||
end
|
||
subgraph "缓存层"
|
||
REDIS["internal/cache/redis.go"]
|
||
end
|
||
MAIN --> CFG
|
||
CFG --> MS_CFG
|
||
MAIN --> MYSQL
|
||
MAIN --> SEARCH_CLIENT
|
||
MAIN --> REDIS
|
||
ROUTER --> HANDLER_MODEL
|
||
ROUTER --> HANDLER_MODEL_LIST
|
||
HANDLER_MODEL --> REPO
|
||
SEARCH_CLIENT --> MS_CFG
|
||
```
|
||
|
||
图表来源
|
||
- [cmd/server/main.go:22-64](file://cmd/server/main.go#L22-L64)
|
||
- [internal/config/config.go:18-51](file://internal/config/config.go#L18-L51)
|
||
- [internal/config/meilisearch.go:14-37](file://internal/config/meilisearch.go#L14-L37)
|
||
- [internal/database/mysql.go:14-46](file://internal/database/mysql.go#L14-L46)
|
||
- [internal/search/meilisearch.go:17-20](file://internal/search/meilisearch.go#L17-L20)
|
||
- [internal/router/router.go:14-41](file://internal/router/router.go#L14-L41)
|
||
- [internal/handler/model.go:19-24](file://internal/handler/model.go#L19-L24)
|
||
- [internal/handler/model_list.go:19-24](file://internal/handler/model_list.go#L19-L24)
|
||
- [internal/repository/model.go:20-61](file://internal/repository/model.go#L20-L61)
|
||
- [internal/model/model.go:5-14](file://internal/model/model.go#L5-L14)
|
||
- [internal/cache/redis.go:10-16](file://internal/cache/redis.go#L10-L16)
|
||
|
||
章节来源
|
||
- [README.md:5-17](file://README.md#L5-L17)
|
||
- [cmd/server/main.go:22-64](file://cmd/server/main.go#L22-L64)
|
||
- [internal/config/config.go:18-51](file://internal/config/config.go#L18-L51)
|
||
|
||
## 核心组件
|
||
- 配置加载与验证:集中加载运行环境、数据库、Meilisearch、Redis 配置,并进行必填项校验
|
||
- Meilisearch 客户端:封装搜索请求,限定返回字段,支持上下文取消
|
||
- 路由与处理器:对外提供 /audio/modelList 搜索接口,支持分页数量控制与可选 Base64 响应
|
||
- 数据访问层:提供按品牌名或型号名的 SQL 查询能力(当前未直接使用 Meilisearch)
|
||
- 缓存层:Redis 客户端,可用于查询结果缓存
|
||
|
||
章节来源
|
||
- [internal/config/meilisearch.go:8-12](file://internal/config/meilisearch.go#L8-L12)
|
||
- [internal/config/meilisearch.go:39-50](file://internal/config/meilisearch.go#L39-L50)
|
||
- [internal/search/meilisearch.go:13-15](file://internal/search/meilisearch.go#L13-L15)
|
||
- [internal/search/meilisearch.go:22-45](file://internal/search/meilisearch.go#L22-L45)
|
||
- [internal/handler/model_list.go:26-56](file://internal/handler/model_list.go#L26-L56)
|
||
- [internal/repository/model.go:20-61](file://internal/repository/model.go#L20-L61)
|
||
- [internal/cache/redis.go:10-16](file://internal/cache/redis.go#L10-L16)
|
||
|
||
## 架构总览
|
||
应用启动时加载配置,建立数据库与 Meilisearch 连接,注册路由并启动 HTTP 服务。搜索请求通过 /audio/modelList 路由进入处理器,处理器调用搜索客户端执行全文检索,最终以 JSON 或 Base64 编码形式返回。
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant Client as "客户端"
|
||
participant Router as "路由"
|
||
participant Handler as "ModelListHandler"
|
||
participant Search as "Meilisearch Client"
|
||
participant Engine as "HTTP 引擎"
|
||
Client->>Engine : "GET /audio/modelList?key=...&count=..."
|
||
Engine->>Router : "匹配 /audio/modelList"
|
||
Router->>Handler : "调用 ModelList()"
|
||
Handler->>Handler : "解析查询参数<br/>解析 count 与 Base64 选项"
|
||
Handler->>Search : "ModelList(ctx, key, count)"
|
||
Search->>Search : "构造 SearchRequest<br/>限制返回字段"
|
||
Search-->>Handler : "返回 hits 列表"
|
||
Handler-->>Client : "JSON 或 Base64 响应"
|
||
```
|
||
|
||
图表来源
|
||
- [internal/router/router.go:32-38](file://internal/router/router.go#L32-L38)
|
||
- [internal/handler/model_list.go:26-56](file://internal/handler/model_list.go#L26-L56)
|
||
- [internal/search/meilisearch.go:22-45](file://internal/search/meilisearch.go#L22-L45)
|
||
|
||
## 详细组件分析
|
||
|
||
### 配置加载与验证
|
||
- 配置结构包含运行环境、监听地址、端口、数据库、Meilisearch、Redis 等字段
|
||
- 加载逻辑按环境选择默认值,支持通过环境变量覆盖
|
||
- Meilisearch 配置包含 Host、APIKey、Index,均需校验非空
|
||
- 启动日志记录已配置的 Meilisearch 主机与索引
|
||
|
||
章节来源
|
||
- [internal/config/config.go:9-16](file://internal/config/config.go#L9-L16)
|
||
- [internal/config/config.go:18-51](file://internal/config/config.go#L18-L51)
|
||
- [internal/config/meilisearch.go:8-12](file://internal/config/meilisearch.go#L8-L12)
|
||
- [internal/config/meilisearch.go:39-50](file://internal/config/meilisearch.go#L39-L50)
|
||
- [cmd/server/main.go:50-54](file://cmd/server/main.go#L50-L54)
|
||
|
||
### Meilisearch 客户端
|
||
- 客户端封装了 IndexManager,负责全文搜索
|
||
- 初始化时传入 Host 与 APIKey,选择指定 Index
|
||
- ModelList 方法接收 key 与 count,限制返回字段,解码为 map 并返回
|
||
- 错误处理统一包装,便于上层捕获
|
||
|
||
```mermaid
|
||
classDiagram
|
||
class Client {
|
||
-index : "IndexManager"
|
||
+NewClient(cfg) : "Client"
|
||
+ModelList(ctx, key, count) : "[]map[string]any, error"
|
||
}
|
||
class MeilisearchConfig {
|
||
+Host : "string"
|
||
+APIKey : "string"
|
||
+Index : "string"
|
||
+validate() : "error"
|
||
}
|
||
Client --> MeilisearchConfig : "依赖"
|
||
```
|
||
|
||
图表来源
|
||
- [internal/search/meilisearch.go:13-20](file://internal/search/meilisearch.go#L13-L20)
|
||
- [internal/search/meilisearch.go:22-45](file://internal/search/meilisearch.go#L22-L45)
|
||
- [internal/config/meilisearch.go:8-12](file://internal/config/meilisearch.go#L8-L12)
|
||
- [internal/config/meilisearch.go:39-50](file://internal/config/meilisearch.go#L39-L50)
|
||
|
||
章节来源
|
||
- [internal/search/meilisearch.go:17-20](file://internal/search/meilisearch.go#L17-L20)
|
||
- [internal/search/meilisearch.go:22-45](file://internal/search/meilisearch.go#L22-L45)
|
||
|
||
### 路由与处理器
|
||
- 路由在 /audio 下注册 /modelList 接口
|
||
- ModelListHandler 解析查询参数 key、count,并支持 Base64 响应
|
||
- 调用搜索客户端执行搜索,错误时返回统一错误响应
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant C as "客户端"
|
||
participant R as "路由"
|
||
participant H as "ModelListHandler"
|
||
participant S as "Meilisearch Client"
|
||
C->>R : "GET /audio/modelList?key=...&count=..."
|
||
R->>H : "ModelList()"
|
||
H->>H : "解析 key/count/base64"
|
||
H->>S : "ModelList(ctx, key, count)"
|
||
S-->>H : "hits"
|
||
H-->>C : "JSON 或 Base64"
|
||
```
|
||
|
||
图表来源
|
||
- [internal/router/router.go:32-38](file://internal/router/router.go#L32-L38)
|
||
- [internal/handler/model_list.go:26-56](file://internal/handler/model_list.go#L26-L56)
|
||
- [internal/search/meilisearch.go:22-45](file://internal/search/meilisearch.go#L22-L45)
|
||
|
||
章节来源
|
||
- [internal/router/router.go:32-38](file://internal/router/router.go#L32-L38)
|
||
- [internal/handler/model_list.go:26-56](file://internal/handler/model_list.go#L26-L56)
|
||
|
||
### 数据访问层(SQL 查询)
|
||
- ModelRepository 支持按品牌名精确匹配与按型号名模糊匹配
|
||
- 默认不使用 Meilisearch,直接走数据库查询
|
||
- 可作为搜索降级路径或补充场景
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
Start(["进入 List"]) --> Trim["去除前后空格"]
|
||
Trim --> Switch{"条件分支"}
|
||
Switch --> |brandName 非空| BrandQuery["按品牌名精确查询<br/>按名称升序"]
|
||
Switch --> |modelName 非空| LikeQuery["按型号名模糊查询<br/>按名称升序"]
|
||
Switch --> |否则| Empty["返回空数组"]
|
||
BrandQuery --> Exec["执行查询"]
|
||
LikeQuery --> Exec
|
||
Exec --> Scan["逐行扫描并组装模型"]
|
||
Scan --> End(["返回结果"])
|
||
Empty --> End
|
||
```
|
||
|
||
图表来源
|
||
- [internal/repository/model.go:20-61](file://internal/repository/model.go#L20-L61)
|
||
- [internal/model/model.go:5-14](file://internal/model/model.go#L5-L14)
|
||
|
||
章节来源
|
||
- [internal/repository/model.go:20-61](file://internal/repository/model.go#L20-L61)
|
||
- [internal/model/model.go:5-14](file://internal/model/model.go#L5-L14)
|
||
|
||
### 数据库连接与模型扫描
|
||
- 使用 go-sql-driver/mysql 建立连接,设置字符集、时区与连接池参数
|
||
- PingContext 超时检测连接可用性
|
||
- 扫描函数将 NullString 转换为指针类型,避免空值污染
|
||
|
||
章节来源
|
||
- [internal/database/mysql.go:14-46](file://internal/database/mysql.go#L14-L46)
|
||
- [internal/repository/model.go:63-86](file://internal/repository/model.go#L63-L86)
|
||
|
||
### 缓存层(Redis)
|
||
- 提供 NewClient 工厂方法,按配置创建 Redis 客户端
|
||
- 可用于搜索结果缓存、热门关键词缓存等
|
||
|
||
章节来源
|
||
- [internal/cache/redis.go:10-16](file://internal/cache/redis.go#L10-L16)
|
||
|
||
## 依赖关系分析
|
||
- 入口 main 依赖配置加载、数据库、Meilisearch、Redis 与路由
|
||
- 路由依赖处理器,处理器依赖搜索客户端与数据库
|
||
- 搜索客户端依赖配置模块与 Meilisearch SDK
|
||
- 数据库层依赖 MySQL 驱动与配置
|
||
|
||
```mermaid
|
||
graph LR
|
||
MAIN["cmd/server/main.go"] --> CFG["internal/config/config.go"]
|
||
MAIN --> MYSQL["internal/database/mysql.go"]
|
||
MAIN --> SEARCH["internal/search/meilisearch.go"]
|
||
MAIN --> REDIS["internal/cache/redis.go"]
|
||
ROUTER["internal/router/router.go"] --> HANDLER1["internal/handler/model.go"]
|
||
ROUTER --> HANDLER2["internal/handler/model_list.go"]
|
||
HANDLER2 --> SEARCH
|
||
HANDLER1 --> REPO["internal/repository/model.go"]
|
||
REPO --> MODEL["internal/model/model.go"]
|
||
```
|
||
|
||
图表来源
|
||
- [cmd/server/main.go:22-64](file://cmd/server/main.go#L22-L64)
|
||
- [internal/config/config.go:18-51](file://internal/config/config.go#L18-L51)
|
||
- [internal/database/mysql.go:14-46](file://internal/database/mysql.go#L14-L46)
|
||
- [internal/search/meilisearch.go:17-20](file://internal/search/meilisearch.go#L17-L20)
|
||
- [internal/cache/redis.go:10-16](file://internal/cache/redis.go#L10-L16)
|
||
- [internal/router/router.go:14-41](file://internal/router/router.go#L14-L41)
|
||
- [internal/handler/model.go:19-24](file://internal/handler/model.go#L19-L24)
|
||
- [internal/handler/model_list.go:19-24](file://internal/handler/model_list.go#L19-L24)
|
||
- [internal/repository/model.go:20-61](file://internal/repository/model.go#L20-L61)
|
||
- [internal/model/model.go:5-14](file://internal/model/model.go#L5-L14)
|
||
|
||
## 性能考虑
|
||
- 索引预处理
|
||
- 在导入数据前,确保字段映射与排序规则已配置,减少运行时开销
|
||
- 对高频查询字段(如品牌名、型号名)建立合适字段权重
|
||
- 查询缓存
|
||
- 使用 Redis 缓存热点搜索结果,设置合理过期时间
|
||
- 对于稳定不变的数据(如品牌列表),可缓存静态结果
|
||
- 分页策略
|
||
- 控制 count 参数上限,避免一次性返回过多数据
|
||
- 结合游标分页或基于主键的分页,提升大结果集性能
|
||
- 连接池与超时
|
||
- 数据库连接池参数已设置,搜索客户端使用短连接或复用连接视场景而定
|
||
- 设置合理的读写超时与上下文取消,防止阻塞
|
||
- 字段裁剪
|
||
- 仅返回必要字段,降低网络传输与序列化成本
|
||
- 相关性与排序
|
||
- 使用 Meilisearch 的排序与过滤能力,避免后端二次排序
|
||
- 日志与监控
|
||
- 记录搜索耗时、命中率与错误统计,便于定位性能瓶颈
|
||
|
||
## 故障排除指南
|
||
- 连接问题诊断
|
||
- 检查 MEILISEARCH_HOST、MEILISEARCH_API_KEY、MEILISEARCH_INDEX 是否正确设置
|
||
- 确认 Meilisearch 服务可达且端口开放
|
||
- 查看启动日志中 Meilisearch 配置是否正确加载
|
||
- 索引重建
|
||
- 如需重建索引,先清空旧索引,再批量导入数据,最后更新字段映射与排序规则
|
||
- 导入完成后进行回归测试,确保搜索结果符合预期
|
||
- 性能调优
|
||
- 逐步增加 count 上限,观察延迟变化,找到平衡点
|
||
- 对热点查询启用缓存,减少重复请求
|
||
- 优化数据库查询(如品牌/型号过滤)作为降级方案
|
||
- 错误处理
|
||
- 搜索失败时返回统一错误响应,便于前端提示
|
||
- 对 decode 失败、上下文取消等异常进行分类处理
|
||
|
||
章节来源
|
||
- [internal/config/meilisearch.go:39-50](file://internal/config/meilisearch.go#L39-L50)
|
||
- [cmd/server/main.go:50-54](file://cmd/server/main.go#L50-L54)
|
||
- [internal/handler/model_list.go:37-42](file://internal/handler/model_list.go#L37-L42)
|
||
- [internal/response/response.go:34-36](file://internal/response/response.go#L34-L36)
|
||
|
||
## 结论
|
||
本项目已实现 Meilisearch 的基础集成:配置加载、客户端初始化与搜索接口。当前搜索接口主要返回指定字段的命中结果,未涉及高亮、自动补全与相关性排序的高级特性。建议后续在以下方面增强:
|
||
- 高亮显示:利用 Meilisearch 的高亮能力,返回匹配片段
|
||
- 自动补全:结合前缀匹配与热门词,提供输入建议
|
||
- 相关性排序:配置字段权重与排序规则,提升搜索体验
|
||
- 索引策略:按业务维度拆分索引,优化写入与查询性能
|
||
- 缓存策略:引入 Redis 缓存,显著降低重复查询延迟
|
||
|
||
## 附录
|
||
|
||
### 搜索 API 使用示例
|
||
- 设备型号搜索
|
||
- 请求:GET /audio/modelList?key=型号关键词&count=100
|
||
- 响应:返回命中的设备列表(仅包含指定字段)
|
||
- 品牌过滤
|
||
- 当前未直接使用 Meilisearch 实现品牌过滤,可通过数据库查询替代
|
||
- 请求:GET /audio/getModel?brandName=品牌名
|
||
- 结果排序
|
||
- 当前未显式设置排序,可结合 Meilisearch 的排序规则实现
|
||
- Base64 响应
|
||
- 可通过查询参数 base64=true 获取 Base64 编码的 JSON
|
||
|
||
章节来源
|
||
- [internal/handler/model_list.go:26-56](file://internal/handler/model_list.go#L26-L56)
|
||
- [internal/handler/model.go:26-50](file://internal/handler/model.go#L26-L50)
|
||
- [internal/search/meilisearch.go:22-45](file://internal/search/meilisearch.go#L22-L45) |