一、Wildcard 概述
Wildcard 是一种支持通配符的模糊检索方式。在 Elasticsearch 中,它使用星号 * 代表零个或多个字符,问号 ? 代表单个字符。
其使用方式多样,例如可以通过 {"wildcard": {"field_name": "value"}} 的形式进行查询。适用场景通常包括召回率要求高的业务场景,当基于分词的全文检索无法满足需求,如基础词库不完备或分词粒度不精确时,Wildcard 可以发挥作用。
然而,Wildcard 也存在一些可能的风险和局限性。从性能角度看,它可能会增加查找匹配项所需的迭代次数,降低搜索性能。尤其当通配符位于检索字段的开头,或者输入的字符串长度过长时,可能导致执行速度极慢,甚至报错。此外,若对用户输入的字符串长度不做限制,可能会造成 CPU 使用率过高、集群宕机等严重后果。
在适用范围上,Wildcard 也有一定的局限性。例如,它不支持依赖于单词位置的查询,如短语查询,并且运行 wildcard 查询时,将忽略任何重写参数,得分总是一个恒定的分数。
二、替代方案
(一)Ngram 分词优化
Ngram 分词通过更细粒度的切分方式来提高数据召回。在配置方面,我们可以设置 min_gram 和 max_gram 参数来控制分词的长度范围。例如,将 min_gram 设置为 1 ,max_gram 设置为 3 ,可以对输入文本进行更细致的切分。在使用时,需要在创建索引或更新字段类型时进行相应配置,指定分析器为 ngram_analyzer 。这样,在搜索时就能更精准地匹配用户输入的模糊查询条件,提高召回效果。
(二)Match_phrase 结合 Ngram
将 match_phrase 与 Ngram 分词相结合,可以进一步增强模糊查询效果。当用户输入模糊查询条件时,先通过 Ngram 分词将查询条件切分成多个词项,然后 match_phrase 会确保这些词项在文档中的顺序一致,从而更准确地匹配用户的意图。例如,对于输入的 "quick fox",Ngram 分词可能会得到 "qui""uic" 等词项,match_phrase 会在文档中查找这些词项且顺序一致的部分,提高查询的准确性和相关性。
(三)Wildcard 字段类型
ES 7.9 版本引入的 wildcard 字段类型为模糊查询提供了新的解决方案。其使用方式较为简单,先定义一个 wildcard 类型的字段,如 PUT my-index-000001{"mappings": {"properties": {"my_wildcard": {"type": "wildcard"}}}} ,然后写入文档,最后通过类似 GET my-index-000001/_search{"query": {"wildcard": {"my_wildcard": "*quite*lengthy"}}} 的查询语句进行搜索。
其原理在于使用了两种数据结构来加速通配符和正则表达式搜索,一是字符串中所有 3 个字符序列的 n-gram 索引,二是完整原始文档值的 "二进制 doc value" 存储。
这种新的字段类型具有明显的优势,在空间大小上与原索引相差不大,而在查询效率方面,对于区分度低的模糊查询场景,优化效率约为之前的 1/3 ,对于区分度高的场景,优化效率约为之前的 1/15 ,显著提升了模糊查询的性能。
三、方案对比与选择
(一)优势对比
- Ngram 分词优化:优势在于能实现更细粒度的切分,从而提高数据召回率。尤其适用于对召回精度要求较高,且基础词库不完善的情况。但可能会增加索引大小和计算成本。
- Match_phrase 结合 Ngram:将顺序匹配和细粒度切分相结合,能够更准确地理解用户意图,提高查询的准确性和相关性。不过配置和使用相对复杂。
- Wildcard 字段类型:新的字段类型显著提升了模糊查询的性能,尤其是在区分度不同的场景下均有优化。使用方式相对简单,对空间大小影响较小。
(二)适用情况
- 当数据量较大,对召回率要求高,但对查询准确性要求相对较低时,可优先选择 Ngram 分词优化。
- 对于需要精准理解用户输入意图,且对查询准确性和相关性要求极高的场景,Match_phrase 结合 Ngram 更为合适。
- 若注重查询性能的提升,同时希望使用方式简单,且对空间影响不大,Wildcard 字段类型是较好的选择。
在实际应用中,应根据具体的业务需求、数据特点和性能要求,综合考虑各方案的优势和适用情况,选择最适合的替代方案。
四、实践案例
假设我们有一个电商平台,需要根据用户输入的模糊关键词搜索相关商品。在过去,使用传统的 Wildcard 查询时,由于性能问题和局限性,导致搜索结果不准确且响应速度慢。
采用 Ngram 分词优化方案:
我们对商品的名称、描述等字段进行了 Ngram 分词优化。例如,对于商品 "红色连衣裙",经过 Ngram 分词处理后,可能会得到 "红""红色""色连""连衣裙" 等词项。当用户输入 "红色裙" 进行搜索时,能够更准确地召回相关商品,提高了召回率,用户能够更快地找到自己想要的商品。
Match_phrase 结合 Ngram 方案应用:
当用户输入 "夏季时尚上衣" 这样的模糊查询条件时,先通过 Ngram 分词将其切分成 "夏季""季时""时尚""尚上""上衣" 等词项,然后 match_phrase 确保这些词项在商品描述中的顺序一致。比如,只有商品描述中同时出现 "夏季 时尚 上衣" 这样顺序的商品才会被召回,大大提高了查询的准确性和相关性,为用户提供了更符合其需求的搜索结果。
Wildcard 字段类型的实践:
假设我们定义了一个 wildcard 类型的字段来存储商品的特殊属性,比如促销标签。当用户输入 "限时" 这样的通配符查询时,能够快速准确地找到带有 "限时折扣""限时优惠" 等标签的商品,提升了搜索效率,同时没有显著增加存储成本。
通过以上实践案例,可以明显看到替代方案在实际场景中的有效应用,为电商平台的搜索功能带来了显著的改进,提升了用户的购物体验。
五、总结与展望
在本文中,我们深入探讨了 Elasticsearch 中 Wildcard 模糊查询的替代方案。
总结而言,Ngram 分词优化通过更细粒度的切分提高了召回率,适用于对召回精度有要求的场景;Match_phrase 结合 Ngram 能更准确地理解用户意图,在对查询准确性和相关性要求极高的情况下表现出色;Wildcard 字段类型则在查询性能和空间占用方面具有优势,使用相对简单。
展望未来,随着数据量的不断增长和用户对搜索体验要求的提高,这些替代方案可能会进一步优化和融合。例如,Ngram 分词的算法可能会更加智能,以更好地平衡索引大小和召回效果;Match_phrase 与 Ngram 的结合可能会更加紧密,提供更灵活和精确的查询方式;Wildcard 字段类型或许会在支持更多复杂的通配符模式和提高处理大规模数据的能力上有所突破。
同时,随着技术的发展,可能会出现新的模糊查询技术和策略,与现有方案相互补充和完善,为 Elasticsearch 的模糊查询提供更强大、更高效的解决方案,以满足不断变化的业务需求和用户期望。