Elasticsearch edge-ngram索引如何支持带空格多词搜索
问题背景
现有Elasticsearch索引分析配置如下:
"analysis" : { "analyzer" : { "global_search_analyzer" : { "filter" : [ "lowercase" ], "tokenizer" : "whitespace" }, "global_search_indexer" : { "filter" : [ "lowercase" ], "type" : "custom", "tokenizer" : "global_search_tokenizer" } }, "tokenizer" : { "global_search_tokenizer" : { "token_chars" : [ "letter", "digit", "custom" ], "custom_token_chars" : "-/[]().,%!\"$#&+'", "min_gram" : "2", "type" : "edge_ngram", "max_gram" : "20" } } }
- 当前配置逻辑:分词器支持指定特殊字符,默认按空格拆分短语。
- 测试示例文档:
{ "_index" : "my_index", "_type" : "_doc", "_id" : "ksdfji319bmm", "_score" : 11.850912, "_source" : { "id" : "ksdfji319bmm", "keywords" : [ "MY TEST" ], "lastUpdateAt" : "2022-07-11", "deleted" : false } }
- keywords字段映射配置:
"keywords" : { "type" : "text", "analyzer" : "global_search_indexer", "search_analyzer" : "global_search_analyzer" }
- 预期效果:搜索
TEST或者MY TEST都能命中上述文档。 - 当前问题:仅搜索
TEST可以正常返回结果,搜索MY TEST无法匹配到该文档,曾尝试将whitespace tokenizer替换为keyword tokenizer,问题仍然存在。
问题根因
问题核心是索引侧edge_ngram分词器的字符规则配置错误:
- edge_ngram分词器会将所有不在
token_chars声明范围内的字符作为分词分割点,当前配置的token_chars只包含字母、数字、自定义特殊字符,空格不在合法字符范围内,也没有加入custom_token_chars。因此写入"MY TEST"时,分词器会先在空格处把文本切分为"MY"、"TEST"两个独立片段,再分别生成edge ngram token,最终索引中仅存在my、te、tes、test这类单单词片段的token,完全没有生成包含空格、跨两个单词的连续token。 - 此前尝试将搜索侧tokenizer换为keyword无法解决问题:该修改只会让搜索
"MY TEST"时生成单个my test的搜索term,但索引中根本不存在对应token,自然无法匹配。
调整方案
- 修改索引侧
global_search_tokenizer配置,将空白字符加入合法token字符范围,让分词器不再以空格为分割点切分多词短语,修改后配置如下:
"tokenizer" : { "global_search_tokenizer" : { "token_chars" : [ "letter", "digit", "custom", "whitespace" ], "custom_token_chars" : "-/[]().,%!\"$#&+'", "min_gram" : "2", "type" : "edge_ngram", "max_gram" : "20" } }
配置修改后,写入"MY TEST"时会将整个短语作为连续文本生成edge ngram token,从长度2的my开始,依次生成my 、my t、my te、my tes、my test等所有前缀token,覆盖单词、多词的搜索场景。
2. 搜索侧analyzer保持原有配置无需修改:
- 搜索单个词如TEST时,whitespace分词器生成test单个term,可以匹配索引中对应前缀token,命中文档。
- 搜索多词短语如MY TEST时,whitespace分词器拆分为my、test两个term,不管是用默认OR逻辑的match查询,还是AND逻辑的match查询、match_phrase_prefix查询,都可以匹配到索引中对应的token,返回目标文档。
3. 配置修改完成后必须重建索引,重新导入全量数据,存量文档不会自动应用新的分词规则。
内容的提问来源于stack exchange,提问作者Avi
相关产品推荐
相关产品推荐

