Files
backend/.qoder/repowiki/zh/content/API参考/材质API/材质搜索.md
lan a4b6c5011e
Some checks failed
SonarQube Analysis / sonarqube (push) Has been cancelled
chore(git): 更新.gitignore以忽略新的本地文件
2025-11-30 08:33:17 +08:00

243 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 材质搜索
<cite>
**本文引用的文件**
- [routes.go](file://internal/handler/routes.go)
- [texture_handler.go](file://internal/handler/texture_handler.go)
- [texture_service.go](file://internal/service/texture_service.go)
- [texture_repository.go](file://internal/repository/texture_repository.go)
- [texture.go](file://internal/model/texture.go)
- [common.go](file://internal/types/common.go)
- [texture_service_test.go](file://internal/service/texture_service_test.go)
</cite>
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考量](#性能考量)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)
## 简介
本文件面向“材质搜索API”的使用与实现围绕关键词搜索、材质类型过滤、公开性筛选与分页功能进行深入解析。基于仓库中的 SearchTextures 查询流程解释关键词匹配名称与描述、类型过滤、公开状态筛选的实现细节并结合分页测试用例说明分页参数的处理规则page小于1时设为1pageSize超过100时设为20。同时提供请求示例、响应数据结构说明与错误处理机制并解释搜索结果中上传者信息的预加载机制Preload及其对性能的影响。
## 项目结构
材质搜索API由三层协作完成
- 路由层:注册 /api/v1/texture 的 GET 搜索接口
- 处理层:解析查询参数、调用服务层并返回分页响应
- 服务层:规范化分页参数、调用仓储层执行查询
- 仓储层:构建查询条件、统计总数、分页查询并预加载上传者信息
```mermaid
graph TB
Client["客户端"] --> Routes["路由: /api/v1/texture(GET)"]
Routes --> Handler["处理器: SearchTextures"]
Handler --> Service["服务: SearchTextures"]
Service --> Repo["仓储: SearchTextures"]
Repo --> DB["数据库"]
Handler --> Resp["分页响应: list,total,page,page_size,total_pages"]
```
图表来源
- [routes.go](file://internal/handler/routes.go#L43-L61)
- [texture_handler.go](file://internal/handler/texture_handler.go#L225-L291)
- [texture_service.go](file://internal/service/texture_service.go#L93-L103)
- [texture_repository.go](file://internal/repository/texture_repository.go#L71-L112)
章节来源
- [routes.go](file://internal/handler/routes.go#L43-L61)
## 核心组件
- 路由注册:在 v1 组下将 GET /api/v1/texture 绑定到处理器 SearchTextures
- 处理器:读取 keyword、type、public_only、page、page_size 查询参数,调用服务层,转换为统一响应结构
- 服务层对分页参数进行边界校正page<1 设为1pageSize<1 >100 设为20再调用仓储层
- 仓储层:按状态=1 进行基础过滤;公开筛选、类型筛选、关键词模糊匹配;先 Count 再分页查询;使用 Preload 预加载上传者信息
章节来源
- [texture_handler.go](file://internal/handler/texture_handler.go#L225-L291)
- [texture_service.go](file://internal/service/texture_service.go#L93-L103)
- [texture_repository.go](file://internal/repository/texture_repository.go#L71-L112)
## 架构总览
下面以序列图展示一次完整搜索请求的调用链路:
```mermaid
sequenceDiagram
participant C as "客户端"
participant R as "路由"
participant H as "处理器"
participant S as "服务层"
participant RE as "仓储层"
participant D as "数据库"
C->>R : GET /api/v1/texture?keyword=&type=&public_only=&page=&page_size=
R->>H : 调用 SearchTextures
H->>H : 解析查询参数<br/>keyword,type,public_only,page,page_size
H->>S : SearchTextures(db, keyword, type, public_only, page, page_size)
S->>S : 校正分页参数<br/>page<1→1pageSize<1或>100→20
S->>RE : SearchTextures(keyword, type, public_only, page, page_size)
RE->>D : 构建查询条件(status=1)<br/>公开筛选(is_public=?)<br/>类型筛选(type=?)
RE->>D : 关键词模糊匹配(name/description)<br/>Count统计总数
RE->>D : 分页查询(Offset/Limit)<br/>Preload上传者信息
D-->>RE : 结果集+总数
RE-->>S : 返回结果集+总数
S-->>H : 返回结果集+总数
H-->>C : 200 + 分页响应
```
图表来源
- [routes.go](file://internal/handler/routes.go#L43-L61)
- [texture_handler.go](file://internal/handler/texture_handler.go#L225-L291)
- [texture_service.go](file://internal/service/texture_service.go#L93-L103)
- [texture_repository.go](file://internal/repository/texture_repository.go#L71-L112)
## 详细组件分析
### 请求参数与处理规则
- 查询参数
- keyword关键词支持名称与描述的模糊匹配
- type材质类型可选 SKIN/CAPE
- public_only布尔值仅返回公开材质
- page页码默认1
- page_size每页数量默认20
- 参数边界校正(服务层)
- page 小于1时设为1
- page_size 小于1时设为20大于100时也设为20
- 类型与公开筛选
- 类型为空字符串时不参与筛选
- public_only 为真时追加 is_public=true 条件
- 关键词匹配
- 同时对 name 和 description 使用 LIKE 模糊匹配
- 排序与分页
- 默认按 created_at 降序排序
- Offset=(page-1)*page_sizeLimit=page_size
- 预加载上传者信息
- 使用 Preload("Uploader") 预加载关联用户信息,便于直接返回上传者字段
章节来源
- [texture_handler.go](file://internal/handler/texture_handler.go#L225-L291)
- [texture_service.go](file://internal/service/texture_service.go#L93-L103)
- [texture_repository.go](file://internal/repository/texture_repository.go#L71-L112)
- [texture_service_test.go](file://internal/service/texture_service_test.go#L163-L215)
### 数据模型与关联
- 材质模型包含上传者外键关联,仓储层通过 Preload 加载上传者信息
- 上传者信息在响应中以嵌套对象形式返回,便于前端直接显示
章节来源
- [texture.go](file://internal/model/texture.go#L16-L35)
### 响应数据结构
- 分页响应包含:
- list结果数组元素为材质信息
- total总条目数
- page当前页码
- page_size每页数量
- total_pages总页数由通用分页响应类型计算
章节来源
- [common.go](file://internal/types/common.go#L18-L25)
- [texture_handler.go](file://internal/handler/texture_handler.go#L225-L291)
### 错误处理机制
- 参数解析失败:返回 400 错误
- 服务内部错误:返回 500 错误
- 业务错误(如材质不存在等)在其他接口中体现,搜索接口主要返回 500 表示查询失败
章节来源
- [texture_handler.go](file://internal/handler/texture_handler.go#L225-L291)
### 分页测试用例要点
- page<1 1
- pageSize<1 20
- pageSize>100 → 20
- 以上规则在服务层统一应用,确保查询稳定性
章节来源
- [texture_service_test.go](file://internal/service/texture_service_test.go#L163-L215)
## 依赖关系分析
- 路由层依赖处理器层
- 处理器层依赖服务层
- 服务层依赖仓储层
- 仓储层依赖数据库层
- 响应结构依赖通用分页类型
```mermaid
graph LR
Routes["routes.go"] --> Handler["texture_handler.go"]
Handler --> Service["texture_service.go"]
Service --> Repo["texture_repository.go"]
Repo --> Model["texture.go"]
Handler --> Types["common.go"]
Service --> Types
```
图表来源
- [routes.go](file://internal/handler/routes.go#L43-L61)
- [texture_handler.go](file://internal/handler/texture_handler.go#L225-L291)
- [texture_service.go](file://internal/service/texture_service.go#L93-L103)
- [texture_repository.go](file://internal/repository/texture_repository.go#L71-L112)
- [texture.go](file://internal/model/texture.go#L16-L35)
- [common.go](file://internal/types/common.go#L18-L25)
## 性能考量
- 预加载上传者信息Preload会增加单次查询的 JOIN 数量,导致额外的网络往返与内存占用。建议:
- 在高频搜索场景中评估是否需要返回上传者信息;若不需要,可在仓储层移除 Preload
- 对搜索结果进行缓存(如 Redis以减少重复 COUNT 与分页查询
- 为常用筛选维度建立合适索引(例如 idx_textures_public_type_status、idx_textures_download_count 等)
- 关键词模糊匹配使用 LIKE 百分号前缀可能导致索引失效,建议:
- 评估是否需要全文检索或倒排索引
- 对高并发场景考虑异步搜索或搜索引擎(如 Elasticsearch
章节来源
- [texture_repository.go](file://internal/repository/texture_repository.go#L71-L112)
- [texture.go](file://internal/model/texture.go#L16-L35)
## 故障排查指南
- 搜索无结果
- 检查 keyword 是否过短或包含特殊字符
- 确认 public_only 是否设置为 true 导致过滤掉私有材质
- 确认 type 是否正确传入SKIN/CAPE
- 分页异常
- page 小于1会被自动修正为1
- page_size 超过100会被修正为20
- 参数错误
- 确认查询参数类型与默认值是否符合预期
- 服务器错误
- 查看服务层日志,确认数据库连接与查询是否报错
章节来源
- [texture_handler.go](file://internal/handler/texture_handler.go#L225-L291)
- [texture_service.go](file://internal/service/texture_service.go#L93-L103)
- [texture_service_test.go](file://internal/service/texture_service_test.go#L163-L215)
## 结论
材质搜索API通过清晰的三层职责划分实现了关键词、类型与公开性三类筛选并以稳健的分页参数校正保障了查询稳定性。预加载上传者信息提升了前端展示效率但需关注其带来的性能成本。建议在生产环境中结合缓存与索引优化进一步提升搜索吞吐与延迟表现。
## 附录
### 请求示例
- 基础搜索(关键词)
- GET /api/v1/texture?keyword=steve
- 类型筛选
- GET /api/v1/texture?type=SKIN
- 公开性筛选
- GET /api/v1/texture?public_only=true
- 组合查询
- GET /api/v1/texture?keyword=cape&type=CAPE&public_only=true&page=1&page_size=20
章节来源
- [texture_handler.go](file://internal/handler/texture_handler.go#L225-L291)
### 响应示例
- 成功响应包含分页字段list、total、page、page_size、total_pages
- 每个材质项包含id、uploader_id、name、description、type、url、hash、size、is_public、download_count、favorite_count、is_slim、status、created_at、updated_at
章节来源
- [common.go](file://internal/types/common.go#L18-L25)
- [texture_handler.go](file://internal/handler/texture_handler.go#L225-L291)