package srv_search import ( "regexp" "strings" ) // 分隔符:空格、英文逗号、中文逗号、顿号、斜杠、竖线 var kwSplitRe = regexp.MustCompile(`[\s,,、/|]+`) // ParseKeywords 解析搜索字符串为关键词列表。 // 规则:去除首尾空格,转小写,按空格/逗号/顿号/斜杠/竖线分割,过滤空串。 func ParseKeywords(q string) []string { q = strings.TrimSpace(q) if q == "" { return nil } parts := kwSplitRe.Split(strings.ToLower(q), -1) result := make([]string, 0, len(parts)) for _, p := range parts { if p = strings.TrimSpace(p); p != "" { result = append(result, p) } } return result } // buildMultiKeywordQuery 构建多关键词 ES bool should 查询(关键词之间 OR 关系)。 // 每个关键词同时生成两个子句: // - 精确 multi_match(权重更高,boost=2) // - 模糊 multi_match(fuzziness=AUTO,prefix_length=1),覆盖拼写错误/多余字符等场景 // // 示例:ChatGPTT→ChatGPT(1次编辑)、midjorny→midjourney(2次编辑)、数智人→数字人(1次编辑) func buildMultiKeywordQuery(keywords []string, fields []string, from, size int) map[string]interface{} { shouldClauses := make([]map[string]interface{}, 0, len(keywords)*2) for _, kw := range keywords { // 精确匹配,分数更高 shouldClauses = append(shouldClauses, map[string]interface{}{ "multi_match": map[string]interface{}{ "query": kw, "fields": fields, "type": "best_fields", "boost": 2, }, }) // 模糊匹配:AUTO fuzziness(长度≥6时允许2次编辑),prefix_length=1 避免过度误召回 shouldClauses = append(shouldClauses, map[string]interface{}{ "multi_match": map[string]interface{}{ "query": kw, "fields": fields, "type": "best_fields", "fuzziness": "AUTO", "prefix_length": 1, "fuzzy_rewrite": "constant_score_blended", }, }) } return map[string]interface{}{ "from": from, "size": size, "query": map[string]interface{}{ "bool": map[string]interface{}{ "should": shouldClauses, "minimum_should_match": 1, }, }, "sort": []map[string]interface{}{ {"_score": map[string]interface{}{"order": "desc"}}, }, } }