es搜索实现既能模糊查询又能分词查询
现在有一个es的字段,希望它既能分词查询,又能有模糊查询怎么办?
只有分词查询的坏处:
可能单个字反而搜不出来,比如一个“南京”,搜“南”字就搜不出来,反而降低体验。
想让es既能分词又能模糊查询有几种办法:
方案一:利用 keyword 子字段实现精确与模糊搜索并存
实现原理
通过为 name 字段添加 keyword 子字段,使其既能进行分词搜索(利用 name 字段自身),又能实现精确或模糊搜索(借助 name.keyword 子字段)。
具体操作步骤
重新定义索引映射
PUT /ebox_material_bizitem/_mapping
{"properties": {"name": {"type": "text","fields": {"keyword": {"type": "keyword","ignore_above": 256}}}}
}
搜索:
GET /ebox_material_bizitem/_search
{"query": {"bool": {"should": [{ "match": { "name": "四" } }, // 分词搜索(如:匹配"四川"、"四季"){ "wildcard": { "name.keyword": "*四*" } } // 模糊搜索(需完整包含"四")],"minimum_should_match": 1}}
}
代码:
nameQuery := elastic.NewBoolQuery().Should(elastic.NewMatchQuery("name", req.GetName()), // 分词搜索elastic.NewWildcardQuery("name.keyword", "*"+req.GetName()+"*"), // 模糊搜索).MinimumNumberShouldMatch(1)queryArgs = append(queryArgs, es.WithMust(nameQuery))
方案二:运用自定义分词器实现多粒度分词
实现原理
创建一个自定义分词器,将文本同时分词为单字和词语,从而兼顾模糊搜索和分词搜索的需求。
方案三:结合 match 和 wildcard 查询
实现原理
在同一个查询中同时使用 match 查询(用于分词搜索)和 wildcard 查询(用于模糊搜索),然后通过 bool.should 将它们组合起来。
GET /ebox_material_bizitem/_search
{"query": {"bool": {"should": [{"match": {"name": {"query": "四","boost": 2 // 提高分词搜索的权重}}},{"wildcard": {"name": {"value": "*四*","boost": 1 // 降低模糊搜索的权重}}}],"minimum_should_match": 1}}
}
用代码实现:
if req.GetName() != "" {nameQuery := elastic.NewBoolQuery().Should(elastic.NewMatchQuery("name", req.GetName()).Boost(2), // 提高分词搜索权重elastic.NewWildcardQuery("name", "*"+req.GetName()+"*").Boost(1), // 降低模糊搜索权重).MinimumNumberShouldMatch(1)queryArgs = append(queryArgs, es.WithMust(nameQuery))}