Iris 模糊搜索需手动拼接 LIKE 子句并转义特殊字符,推荐用 query string 传参、限制长度、避免左模糊以保索引有效。

模糊搜索必须手动拼接 SQL LIKE 子句,Iris 不提供 ORM 层
Iris 的 MVC 架构本身不带数据库抽象或查询构建器,Service 层需自行对接 database/sql、gorm 或 sqlx 等驱动。模糊搜索逻辑完全落在你写的查询语句里,框架只负责把参数传进 controller 方法、把结果序列化返回。
常见错误是以为用 ctx.URLParam("q") 拿到关键词后直接塞进 WHERE name = ? —— 这不是模糊搜索,这是等值匹配。
- 关键词前后必须加
%才能实现“包含”语义,但不能在 SQL 里硬写WHERE name LIKE '%?%'(会报语法错) - 正确做法是 Go 层拼好带通配符的字符串,再作为参数传给
QueryRow或Find - 若用
gorm,需显式调用Where("name LIKE ?", "%"+q+"%"),不能依赖Where("name", q)
Controller 中如何安全接收并清洗模糊搜索关键词
用户输入的关键词可能含 SQL 元字符(如 %、_、),若不做处理直接拼进 LIKE,会导致意料外的匹配或注入风险。Iris 不自动转义,这步必须手写。
推荐做法:用 strings.TrimSpace 去首尾空格,再用 strings.ReplaceAll 对特殊字符做转义(如果底层 DB 支持 ESCAPE),或更简单——直接过滤掉所有非字母数字字符(适用于中文场景可改用正则保留汉字)。
q := strings.TrimSpace(ctx.URLParam("q"))- 若允许用户输入通配符,且 DB 是 MySQL/PostgreSQL,需统一 escape 字符,例如:
q = strings.ReplaceAll(q, ``, `\`); q = strings.ReplaceAll(q, `%`, `%`); q = strings.ReplaceAll(q, `_`, `_`),然后 SQL 写WHERE name LIKE ? ESCAPE '' - 生产环境建议限制最大长度,比如
if len(q) > 50 { ctx.StatusCode(400); ctx.JSON(BizError{Code: 40003, Msg: "搜索词过长"}); return }
路径设计与参数传递:用 query string 还是 path param?
模糊搜索本质是可选、非必需的筛选条件,应走 GET /users?q=xxx&page=1 这类 query string,而不是 GET /users/search/{q}。后者会让路由系统把 /users/search/ 当作固定前缀,一旦用户搜空字符串或含斜杠的词(如 foo/bar),路径解析直接失败或 404。
- controller 方法签名应为
func (c *UserController) Get() []User,内部用ctx.URLParam("q")取值 - 避免写
func (c *UserController) GetSearch(q string) []User—— 这要求你在BeforeActivation里注册b.Handle("GET", "/search/{q:string}", "GetSearch"),但{q:string}无法匹配含/、?、&的原始输入 - 分页参数同理,
page和limit也走 URL query,不要塞进 path
性能陷阱:LIKE '%xxx' 会失效索引,必须用前缀匹配或全文索引
当搜索词放在 LIKE 左侧(WHERE name LIKE '%xxx'),MySQL/PostgreSQL 无法使用 B-tree 索引,全表扫描不可避免。这是模糊搜索最常被忽略的性能雷区。
解决方向只有两个:要么改查询模式,要么换索引类型。
- 若业务允许“以某串开头”,强制用
WHERE name LIKE 'xxx%',此时索引有效 - 若必须“包含”,且数据量大(>10 万行),需建全文索引(MySQL 的
FULLTEXT,PostgreSQL 的tsvector),并改用MATCH ... AGAINST或to_tsvector @@ to_tsquery - 临时方案:加缓存,对高频搜索词(如
admin、test)用redis缓存结果,设置短 TTL
别指望 Iris 自动优化这个 —— 它连 SQL 都不碰,所有性能责任都在你的 Service.FindUsersByKeyword() 里。


















