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