简介
本接口文档面向电商应用开发者,提供“商品搜索”能力的完整接口参考。当前仓库实现了统一的站内搜索入口,支持按关键词检索、模块筛选(如商品)、分类筛选、分页与排序等能力;同时提供了商品列表的独立接口,支持品牌筛选与排序。本文档将基于源码梳理:
- 搜索接口的 HTTP 方法、URL 路径与参数规范
- 搜索算法覆盖范围(标题/描述/内容匹配、多语言标题匹配)
- 高级筛选(分类、品牌)与排序(销量、价格、更新时间、自定义排序)
- 搜索结果结构与分页
- 请求与响应示例
- 性能优化建议
项目结构
搜索相关代码主要分布在以下位置:
- API 路由与控制器:定义 /api/?route=search 的 GET 搜索接口
- 前台服务与模型:实现跨模块 UNION 查询、分页、排序选项构建与结果格式化
- 商品服务:提供商品列表与详情能力,包含品牌筛选与排序
graph TB
Client["客户端"] --> Route["API 路由<br/>search.php"]
Route --> Ctl["SearchController<br/>index()"]
Ctl --> Svc["SearchService<br/>buildSearchResultData()"]
Svc --> Sort["ListSortOptionBuilder<br/>buildSortOptions()"]
Svc --> Model["Search<br/>buildUnionSearchQuery()/fetchUnionSearchRows()"]
Model --> DB["数据库"]
核心组件
- API 路由:声明 search 路由,映射到 SearchController::index
- API 控制器:接收 q、module、category_id、page、by、sort 等参数,调用服务层并返回统一 JSON
- 搜索服务:组装查询、排序、分页与结果格式化
- 搜索模型:按模块动态生成 UNION ALL 查询,支持标题/内容/多语言标题匹配与分类过滤
- 排序构建器:根据配置与传入 by/sort 生成前端排序项与 SQL 片段
- 商品服务:提供商品列表与详情,支持品牌筛选与排序
架构总览
搜索流程从 API 路由进入,控制器校验参数后交由服务层处理。服务层根据是否指定 module 决定搜索范围;若为 product 则启用商品专属排序;最终通过模型层执行 UNION 查询并分页返回。
sequenceDiagram
participant C as "客户端"
participant R as "路由"
participant Ctrl as "SearchController"
participant S as "SearchService"
participant M as "Search 模型"
participant D as "数据库"
C->>R : GET /api/?route=search&q=...&module=product&category_id=...&page=...&by=...&sort=...
R->>Ctrl : index(request)
Ctrl->>Ctrl : 校验 q/module/category_id/page/by/sort
Ctrl->>S : buildSearchResultData(keyword, module, catId, page, sortBy, sortDir)
S->>S : 计算排序选项与SQL
S->>M : buildUnionSearchQuery(...)
M->>D : 执行UNION查询(标题/内容/多语言标题匹配)
D-->>M : 结果集
M-->>S : 分页数据(list, pager)
S-->>Ctrl : 格式化后的search_list与元信息
Ctrl-->>C : ApiResponse.success(data)
详细组件分析
搜索接口规范
- HTTP 方法:GET
- URL 路径:/api/?route=search
- 必需/可选参数:
- q:搜索关键词(字符串,空表示不限)
- module:限定模块,如 product(字母,未传或非法时回退默认)
- category_id:分类 ID(整数,0 表示不限)
- page:页码(整数,默认 1)
- by:排序字段(字符串,如 sales/price/created_at/sort)
- sort:排序方向(asc/desc,仅对可切换字段生效)
- 响应格式:统一成功包装,data 中包含 title、keyword、search_module、search_results、search_list、sort_list 等
搜索算法与匹配范围
- 关键词匹配:
- 单语言模式:在标题与内容中模糊匹配(LIKE %keyword%)
- 多语言模式:关联 language_value,按标题译文进行 LIKE 匹配
- 模块范围:
- 未指定 module:按配置的 column_module 列表进行 UNION ALL 合并
- 指定 module:仅在该模块内检索(例如 product)
- 分类筛选:
- 当 category_id > 0 时,限定在该分类及其子分类内
- 状态过滤:
- 若表存在 status 字段,则只取 status = 1 的记录
flowchart TD
Start(["开始"]) --> CheckQ["检查关键词是否为空"]
CheckQ --> |为空| ListMode["无关键词列表模式"]
CheckQ --> |非空| BuildQuery["按模块构建子查询"]
BuildQuery --> Lang{"是否开启多语言?"}
Lang --> |是| MatchTitleLang["按language_value.title匹配"]
Lang --> |否| MatchTitleContent["按title/content匹配"]
MatchTitleLang --> CatFilter{"是否指定分类?"}
MatchTitleContent --> CatFilter
CatFilter --> |是| Subtree["获取子分类ID集合并whereIn"]
CatFilter --> |否| StatusCheck{"是否存在status字段"}
Subtree --> StatusCheck
StatusCheck --> |是| FilterStatus["where status=1"]
StatusCheck --> |否| UnionAll["UNION ALL合并各模块"]
FilterStatus --> UnionAll
UnionAll --> Order["应用排序SQL"]
Order --> End(["结束"])
高级搜索选项
- 分类筛选:通过 category_id 限定至该分类及子分类
- 品牌筛选:商品列表接口支持 brand_id 参数(见商品列表接口)
- 评分筛选:当前搜索接口未暴露评分筛选参数
- 价格区间筛选:当前搜索接口未暴露价格区间参数
说明:
- 搜索接口本身不直接支持价格区间与评分筛选;如需此类能力,可在上层封装或在商品列表接口中组合使用
- 品牌筛选可通过商品列表接口实现,再结合业务逻辑形成“搜索+筛选”的组合体验
排序功能
- 支持的排序字段:sales(销量)、price(价格)、created_at(发布时间)、sort(自定义排序)
- 排序方向:
- price 字段支持 asc/desc 切换
- 其他字段默认方向由构建器决定
- 默认排序:created_at DESC, id DESC(搜索);商品列表默认 sort ASC, id DESC
- 排序选项构建:
- 根据配置 features.order 决定是否暴露销量排序
- 生成前端排序项与对应 SQL 片段
classDiagram
class ListSortOptionBuilder {
+buildSortOptions(fields, options, default_sort, by, sort, page_url, table_alias) array
}
class SearchService {
+buildSearchResultData(keyword, searchModule, catId, page, sortBy, sortDir) array
}
class ProductService {
+buildProductListData(catId, page, pageSize, brandId, sortBy, sortDir, archive, isApi, userId, allCategories) array
}
SearchService --> ListSortOptionBuilder : "使用"
ProductService --> ListSortOptionBuilder : "使用"
搜索结果结构
- search_list:当前页结果数组,每项包含 id、module、name/title、price、image/thumbnail、created_at、description、url、cate_info 等
- pager:分页信息(list、pager 键结构来自底层分页)
- sort_list:排序选项数组(用于前端渲染)
- keyword、search_module、title、search_results:页面级元信息
请求与响应示例
- 请求示例(搜索商品):
- GET /api/?route=search&q=手机&module=product&category_id=10&page=1&by=price&sort=asc
- 响应示例(简化):
- code: 200
- data:
- title: “搜索结果”
- keyword: “手机”
- search_module: “product”
- search_results: “找到 X 个结果”
- search_list: [...]
- sort_list: [...]
说明:
- 以上为基于源码行为的示例化描述;实际字段以服务端返回为准
智能搜索(建议与热门搜索)
- 当前仓库未实现独立的“搜索建议”或“热门搜索词”接口
- 可在现有搜索接口基础上扩展:
- 缓存高频关键词并返回 top N
- 基于用户历史或全站统计生成建议
- 建议作为后续增强点,不在本次版本范围内
依赖关系分析
- 路由依赖控制器:search 路由绑定 SearchController::index
- 控制器依赖服务:SearchController 注入 SearchService
- 服务依赖排序构建器与模型:SearchService 使用 ListSortOptionBuilder 生成排序 SQL,使用 Search 模型构建 UNION 查询
- 模型依赖数据库:Search 模型通过 ORM 构造子查询并执行分页
graph LR
Route["search.php"] --> Controller["SearchController.php"]
Controller --> Service["SearchService.php"]
Service --> Sort["ListSortOptionBuilder.php"]
Service --> Model["Search.php"]
Model --> DB["数据库"]
性能考虑
- 查询优化
- 使用 UNION ALL 合并多模块结果,避免重复扫描
- 仅在必要时关联 language_value 表进行多语言标题匹配
- 分类筛选通过子树 ID 列表 with inWhere 减少全表扫描
- 索引建议
- 为标题、内容、创建时间、分类 ID 建立合适索引以提升 LIKE 与排序效率
- 对频繁排序字段(如 created_at、price)建立索引
- 分页与限流
- 合理设置每页条数(search 专用 > product > article > 默认 10)
- 对搜索接口实施限流策略,防止恶意高频请求
- 缓存策略
- 对热门搜索词与热门分类结果进行短期缓存
- 对静态排序选项与分类树进行缓存
故障排查指南
- 关键词校验失败
- 现象:抛出领域异常,提示关键词无效
- 原因:q 参数未通过关键字校验规则
- 处理:检查输入是否符合规则,或清空关键词重试
- 模块名非法
- 现象:module 非字母或未在允许列表中,将被忽略或置空
- 处理:确保 module 为合法字母串且在配置的 column_module 中
- 分类不存在或无效
- 现象:category_id 无法解析或无子分类
- 处理:确认分类 ID 有效;若为 0 或不传则不限分类
- 排序参数错误
- 现象:by/sort 不合法导致回退默认排序
- 处理:使用支持的字段与方向(如 by=sales&sort=desc)
结论
当前仓库提供了统一的站内搜索入口,支持关键词搜索、模块与分类筛选、分页与排序,并在商品场景下支持品牌筛选与多种排序方式。对于价格区间与评分筛选、搜索建议与热门搜索等功能,可在现有基础上进行扩展。建议在上线前完善索引与缓存策略,并结合限流保障稳定性。
附录
接口清单
- 站内搜索
- 方法:GET
- 路径:/api/?route=search
- 参数:q、module、category_id、page、by、sort
- 响应:统一成功包装,data 包含搜索列表与元信息
- 商品列表(辅助筛选)
- 方法:GET
- 路径:/api/?route=product
- 参数:id/category_slug、brand_id、by、sort、page 等
- 响应:商品列表、分页、排序选项、品牌信息