如何在Elasticsearch中仅搜索与词汇绑定的数字
实现单词与数字的绑定匹配方案
要实现查询“bottles 200”时仅返回包含该连续短语的结果,而非匹配“glass 200”这类无关组合,可通过以下两种方式解决:
方案一:使用短语查询(无需修改现有分词配置)
直接采用match_phrase查询替代普通match,该查询会严格匹配词的顺序与相邻关系,确保只有包含“bottles 200”连续短语的文档被返回。
示例查询DSL:
{ "query": { "match_phrase": { "目标字段名": "bottles 200" } } }
若需要允许短语中间存在少量非关键词(如停用词),可添加slop参数调整宽松度,但针对你的精确匹配需求,无需额外配置。
方案二:修改分词配置,将单词与数字绑定为单个Token
通过自定义字符过滤器,将“单词+空格+数字”的组合转换为无空格的整体Token,从存储层面实现绑定。
1. 更新分析器配置
在现有配置中新增字符过滤器,并调整分析器的字符过滤器顺序:
'body' => [ 'settings' => [ 'analysis' => [ "char_filter"=>[ "ru"=>[ "type"=>"mapping", "mappings"=>['Ё=>Е', 'ё=>е'], ], // 新增:绑定单词与数字的字符过滤器 "word_number_binder"=>[ "type"=>"pattern_replace", "pattern"=>"([a-zA-Zа-яА-Я]+)\\s+(\\d+)", "replacement"=>"$1_$2" ] ], "analyzer"=>[ "ru_RU_analizer"=>[ "tokenizer"=>"standard", // 加入新增的字符过滤器,放在最前面执行 "char_filter"=>["ru", "word_number_binder"], "filter"=>["stopwords_ru", "stop", "custom_word_delimiter", "lowercase", "ru_RU"], ] ], // 原有过滤器配置保持不变 "filter"=>[ "ru_RU"=>[ "type"=>"hunspell", "language"=>"ru_RU", ], "stopwords_ru"=>[ "type"=> "stop", "ignore_case"=>true ], "custom_word_delimiter"=>[ "type"=>"word_delimiter", "generate_word_parts"=>true, "generate_number_parts"=>true , "catenate_words"=>true, "catenate_numbers"=>false, "catenate_all"=>true, "split_on_case_change"=>true, "preserve_original"=> true, "split_on_numerics"=>false, ], ], ], ] ]
2. 重建索引并重新导入数据
分词配置修改后,需删除原索引,使用新配置重建索引,再重新导入数据,确保新的Token规则生效。
3. 查询匹配
查询“bottles 200”时,分析器会自动将其转换为bottles_200单个Token,直接匹配存储的绑定Token即可。
方案对比
- 方案一:快速生效,无需改动索引结构,适合临时需求或希望保留原有分词逻辑的场景。
- 方案二:从存储层固化绑定关系,适合长期将“单词+数字”组合视为整体的场景,但需要重建索引。
内容的提问来源于stack exchange,提问作者Valya Gromov
相关产品推荐
相关产品推荐

