Elasticsearch如何配置分析器匹配.com/.net等带点号关键词
我当前使用如下自定义分析器配置:
"settings": { "analysis": { "char_filter": { "my_char_filter": { "type": "mapping", "mappings": [ "- => _" ] }, "quote_filter": { "type": "mapping", "mappings": [ "\\u0091=>\\u0020", "\\u0092=>\\u0020" ] } }, "analyzer": { "my_analyzer": { "tokenizer": "standard", "char_filter": [ "my_char_filter", "quote_filter" ], "filter": [ "lowercase" ] } } } }
配套使用如下mapping配置,普通关键词检索可正常运行:
"mappings": { "properties": { "title": { "type": "text", "analyzer": "my_analyzer", "term_vector": "with_positions_offsets" }, "description": { "type": "text", "analyzer": "my_analyzer", "term_vector": "with_positions_offsets", "fielddata": true } } }
当使用如下查询语句,在描述文本 Google.com is an American multinational technology company (COM) that focuses on artificial intelligence, search engine technology, online advertising, cloud computing and computer software 中检索.com时,仅能匹配括号内的“COM”,无法匹配目标.com:
{ "query": { "bool": { "must": [ { "query_string": { "query": "\".net\" OR \".com\"", "fields": [ "title", "description" ] } } ] } }, "highlight": { "pre_tags": ["<match>"], "post_tags": ["</match>"], "fields": { "title": { "type": "fvh", "number_of_fragments": 0 }, "description": { "type": "fvh", "number_of_fragments": 0 } } } }
补充测试情况
调整查询语句移除关键词的引号,修改为如下查询后仅能部分匹配:
"query_string" : { "query" : ".com OR .net OR Engine OR American", "fields": ["title","description"] }
该查询可匹配“Engine”和“American”,返回的匹配关键词集合为matched_keywords: {'Engine', 'American', 'Google.com'},但无法明确识别是否匹配前缀为任意字符的.com/.net类带点号关键词,期望能返回格式类似matched_keywords: {'Engine', 'American', '*.com'}的明确匹配结果。
核心问题出在你选用的standard标准分词器:
- 标准分词器默认将点号
.作为分词分隔符处理,文本写入索引时,Google.com会被直接拆成google、com两个独立token,点号会被完全丢弃 - 检索阶段输入的
.com经过相同分析链路处理时,开头的点号会被过滤,最终只剩com这个token,所以只会匹配到文本里单独出现的COM(经lowercase过滤器转成小写后命中),根本识别不到带点的域名后缀 - 去掉引号后能命中
Google.com,本质是query_string语法中未加转义的.默认代表任意单个字符的通配符,属于模糊匹配碰中,无法稳定识别所有.com/.net后缀的词,也没法做明确的匹配标记。
分两步调整即可完全满足需求:
第一步:替换分词器,保留域名后缀特征
把原来的standard分词器换成官方自带的uax_url_email分词器,这个分词器专门为包含URL、邮箱、域名的文本设计,会自动把xxx.com、xxx.net这类域名识别成完整token,不会拆分点号,也不会丢失后缀特征。
修改后的分析器配置如下:
"settings": { "analysis": { "char_filter": { "my_char_filter": { "type": "mapping", "mappings": [ "- => _" ] }, "quote_filter": { "type": "mapping", "mappings": [ "\\u0091=>\\u0020", "\\u0092=>\\u0020" ] } }, "analyzer": { "my_analyzer": { "tokenizer": "uax_url_email", "char_filter": [ "my_char_filter", "quote_filter" ], "filter": [ "lowercase" ] } } } }
注意:修改分词器配置后必须重建索引,存量数据重新导入,新的分词规则才会生效。
第二步:调整查询语句,实现明确后缀匹配
不要给.com/.net关键词加引号(加引号会强制精确短语匹配,反而因为token规则不匹配失效),直接用后缀通配符写法,同时开启通配符分析保证大小写匹配逻辑一致。
修改后的查询语句:
{ "query": { "bool": { "must": [ { "query_string": { "query": "*.com OR *.net OR Engine OR American", "fields": ["title", "description"], "analyze_wildcard": true } } ] } }, "highlight": { "pre_tags": ["<match>"], "post_tags": ["</match>"], "fields": { "title": { "type": "fvh", "number_of_fragments": 0 }, "description": { "type": "fvh", "number_of_fragments": 0 } } } }
效果说明
配置生效后用测试文本验证:
- 不会再误匹配括号内单独出现的
COM,只会正确命中带后缀的Google.com - 普通关键词(Engine、American)的匹配逻辑和之前完全一致,不受影响
- 业务层可以直接把所有以
.com/.net结尾的命中词统一标记为*.com/*.net类匹配,完全符合预期的返回格式。
内容的提问来源于stack exchange,提问作者Sandy

