fix(makecode): Search 文本字段只走模糊匹配,避免等值叠加导致空结果
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+5
-1
@@ -980,7 +980,11 @@ func (that *MakeCode) Search(table string, userData Map, data Map, req *http.Req
|
|||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
reqValue := req.FormValue(v.GetString("name"))
|
reqValue := req.FormValue(v.GetString("name"))
|
||||||
if v.GetString("name") != "parent_id" && reqValue != "" {
|
// text 类字段只走下方模糊匹配([~]),此处不再生成等值条件,
|
||||||
|
// 否则等值(必不命中部分关键词)与模糊匹配在 where 中以 AND 叠加,
|
||||||
|
// 查询恒为空(见 docs/CodeGen_代码生成.md 通用 Search 筛选说明)。
|
||||||
|
if v.GetString("name") != "parent_id" && reqValue != "" &&
|
||||||
|
!strings.Contains(v.GetString("type"), "text") {
|
||||||
data[v.GetString("name")] = reqValue
|
data[v.GetString("name")] = reqValue
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -765,6 +765,17 @@ CREATE TABLE user (
|
|||||||
|
|
||||||
**规则**:`showself=1` 仅在 `showall=1` 时生效。普通子级查询(仅 `parent_id=X`)**不会**把 id=X 的行本身混入结果——否则前端树会把节点当作自己的子级,造成无限嵌套(历史缺陷,已修复;回归用例见 `example/app/makecode_tree_test.go`,`go test ./app/ -count=1 -run 'TestApi/admin/department/search'`)。
|
**规则**:`showself=1` 仅在 `showall=1` 时生效。普通子级查询(仅 `parent_id=X`)**不会**把 id=X 的行本身混入结果——否则前端树会把节点当作自己的子级,造成无限嵌套(历史缺陷,已修复;回归用例见 `example/app/makecode_tree_test.go`,`go test ./app/ -count=1 -run 'TestApi/admin/department/search'`)。
|
||||||
|
|
||||||
|
#### 通用列表字段筛选语义(text 类型只走模糊匹配)
|
||||||
|
|
||||||
|
通用 CRUD 的 `search` 接口为每个 `list` 可见字段自动生成筛选条件(`code/makecode.go` `(*MakeCode).Search`),按字段最终生效的 `type`(见 [4.2 数据类型映射](#42-数据类型映射),可被 [3.3 字段规则配置(rule.json)](#33-字段规则配置rulejson) 覆盖)分两种语义:
|
||||||
|
|
||||||
|
| 字段 type | 请求 `?字段名=值` 的 WHERE 语义 | 说明 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| 含 `"text"` 子串(`text`/`textArea`) | `字段名 LIKE '%值%'`(模糊,仅此一条) | 前端筛选框允许只填部分关键词 |
|
||||||
|
| 其他(`number`/`select`/`time`/`money`… 等非 text) | `字段名 = 值`(精确等值) | 维持现状不变 |
|
||||||
|
|
||||||
|
**规则**:文本类型字段**只生成模糊匹配条件,不再叠加同名等值条件**。历史缺陷:曾对所有 list 字段先生成等值条件 `字段名=值`,再对 text 类型**额外**叠加模糊条件 `字段名[~]=值`,两者在 where 里以 AND 叠加——前端筛选框只传部分关键词时等值条件必不命中,AND 之后整条查询恒为空(下游"文本列筛选查不出数据"的通用根因)。已修复;`keyword`+`keywordtable` 全局关键词搜索逻辑不受影响。回归用例见 `example/app/makecode_tree_test.go` 的「文本字段部分关键词命中模糊匹配」「非文本字段等值筛选行为不变」两个用例,`go test ./app/ -count=1 -run 'TestApi/admin/department/search'`。
|
||||||
|
|
||||||
### 4.5 生成的代码结构
|
### 4.5 生成的代码结构
|
||||||
|
|
||||||
#### 内嵌模式 (mode=0)
|
#### 内嵌模式 (mode=0)
|
||||||
|
|||||||
@@ -104,6 +104,46 @@ var AdminDepartmentTest = ProjTest{
|
|||||||
return nil
|
return nil
|
||||||
}).
|
}).
|
||||||
Get("showall加showself含自身与子孙", 0, rowSample)
|
Get("showall加showself含自身与子孙", 0, rowSample)
|
||||||
|
|
||||||
|
// ======== 修复回归:文本字段部分关键词模糊匹配 + 非文本字段等值筛选不受影响 ========
|
||||||
|
// 背景 bug(code/makecode.go Search):文本类字段(如 name)曾同时生成等值条件
|
||||||
|
// name=值 与模糊条件 name[~]=值,二者在 where 中以 AND 叠加;前端筛选框传入
|
||||||
|
// 部分关键词时等值条件必不命中,AND 之后查询恒为空。
|
||||||
|
// 修复后:文本字段只走模糊匹配;非文本字段(如 state,规则覆盖为 select 类型)维持等值匹配现状。
|
||||||
|
textId := a.DB().Insert("department", Map{
|
||||||
|
"name": "综合行政部", "state": 5, "parent_id": nodeX,
|
||||||
|
"create_time[#]": "NOW()", "modify_time[#]": "NOW()",
|
||||||
|
})
|
||||||
|
a.DB().Update("department", Map{"parent_ids": "," + ObjToStr(rootId) + "," + ObjToStr(nodeX) + "," + ObjToStr(textId) + ","}, Map{"id": textId})
|
||||||
|
|
||||||
|
a.WithSession(session).
|
||||||
|
Note("修复前:name 等值(综合行政部≠行政)与模糊[~]同时AND叠加,传部分关键词恒查不到;修复后应命中模糊匹配").
|
||||||
|
Query(Map{"parent_id": rootId, "showself": "1", "showall": "1", "pageSize": "50", "name": "行政"}).
|
||||||
|
Verify(func(a *Api) error {
|
||||||
|
ids := resultIds(a)
|
||||||
|
if !ids[textId] {
|
||||||
|
return fmt.Errorf("文本字段部分关键词模糊查询应命中 id=%d, 实际: %v", textId, ids)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}).
|
||||||
|
Get("文本字段部分关键词命中模糊匹配", 0, rowSample)
|
||||||
|
|
||||||
|
a.WithSession(session).
|
||||||
|
Note("state 规则覆盖为 select 类型(非text),应维持等值匹配现状,只精确命中 state=5 的记录").
|
||||||
|
Query(Map{"parent_id": rootId, "showself": "1", "showall": "1", "pageSize": "50", "state": "5"}).
|
||||||
|
Verify(func(a *Api) error {
|
||||||
|
ids := resultIds(a)
|
||||||
|
if !ids[textId] {
|
||||||
|
return fmt.Errorf("非文本字段等值筛选应命中 id=%d, 实际: %v", textId, ids)
|
||||||
|
}
|
||||||
|
for id := range ids {
|
||||||
|
if id != textId {
|
||||||
|
return fmt.Errorf("非文本字段等值筛选不应包含其它 state 的记录,实际额外命中: id=%d", id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}).
|
||||||
|
Get("非文本字段等值筛选行为不变", 0, rowSample)
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user