如何为邮箱ID定制Elasticsearch分词实现精准前缀匹配?
实现Elasticsearch邮箱自定义分词方案
需求明确
你需要针对邮箱ID实现两类自定义分词,核心规则如下:
类别1
- 按标点(
.、@)分割出独立词汇 - 对每个分割后的词汇生成从开头起始的前缀分词(如
ona生成on、ona)
类别2
- 包含类别1的所有分词结果
- 额外生成包含标点的前缀分词(如
ona.、ona.k、.ki@等)
匹配规则
- 需匹配:从词汇/邮箱起始位置开始的前缀(含标点),如
ona.k、.ki@、ki@ - 不匹配:非起始位置的子串,如
na.k、i@
场景需求
当用户搜索on、ona等前缀时,仅返回匹配ona.ki@gl.com的文档,排除mona.gh@gl.com。
可以实现,以下是具体方案
Elasticsearch支持通过自定义分析器组合分词器、令牌过滤器来实现这类特殊分词逻辑,以下是两类分词的具体配置:
类别1:按标点分割+前缀分词
创建索引时定义自定义分析器,核心逻辑是先按标点分割词汇,再对每个词汇生成前缀令牌:
PUT /email_index_v1 { "settings": { "analysis": { "analyzer": { "email_analyzer_v1": { "tokenizer": "email_tokenizer", "filter": ["lowercase", "email_edge_ngram"] } }, "tokenizer": { "email_tokenizer": { "type": "pattern", "pattern": "[.@]", "split_on_match": true } }, "filter": { "email_edge_ngram": { "type": "edge_ngram", "min_gram": 2, "max_gram": 20, "side": "front" } } } }, "mappings": { "properties": { "email": { "type": "text", "analyzer": "email_analyzer_v1", "search_analyzer": "standard" } } } }
验证分词效果
调用_analyze接口测试:
POST /email_index_v1/_analyze { "analyzer": "email_analyzer_v1", "text": "ona.ki@gl.co" }
生成的令牌符合类别1需求:on、ona、ki、gl、co等(分割后的词汇及前缀)。
类别2:含标点的前缀分词
这类分词需要保留包含标点的前缀,需结合pattern_capture过滤器捕获所有符合规则的子串,再生成前缀令牌:
PUT /email_index_v2 { "settings": { "analysis": { "analyzer": { "email_analyzer_v2": { "tokenizer": "keyword", "filter": ["lowercase", "email_pattern_capture", "email_edge_ngram", "unique"] } }, "filter": { "email_pattern_capture": { "type": "pattern_capture", "patterns": [ "^.{2,}", // 捕获整个邮箱从开头的所有长≥2的子串 "(\\.[^@]+)", // 捕获`.`后的所有内容 "(@.*)", // 捕获`@`后的所有内容 "([^.@]{2,})" // 捕获分割后的纯字母长≥2的词汇 ] }, "email_edge_ngram": { "type": "edge_ngram", "min_gram": 2, "max_gram": 20, "side": "front" } } } }, "mappings": { "properties": { "email": { "type": "text", "analyzer": "email_analyzer_v2", "search_analyzer": "standard" } } } }
验证分词效果
调用_analyze接口测试:
POST /email_index_v2/_analyze { "analyzer": "email_analyzer_v2", "text": "ona.ki@gl.co" }
生成的令牌完全匹配你给出的示例,包括ona.、ona.k、.ki@、ki@等含标点的前缀分词。
场景验证
针对你的需求场景,使用类别1的分析器即可实现精准匹配:
- 向索引中添加两个文档:
POST /email_index_v1/_doc/1 { "email": "ona.ki@gl.com" } POST /email_index_v1/_doc/2 { "email": "mona.gh@gl.com" }
- 搜索
on:
POST /email_index_v1/_search { "query": { "match": { "email": "on" } } }
仅会返回ona.ki@gl.com的文档,因为mona的前缀令牌为mo、mon、mona,不会匹配on。
注意事项
- 调整
edge_ngram的max_gram参数适配你的邮箱最大长度,避免生成过多冗余令牌。 - 如果不需要大小写敏感,保留
lowercase过滤器即可;若需区分大小写,可移除该过滤器。 - 始终通过
_analyze接口测试分析器效果,根据实际需求调整正则表达式或过滤器参数。
内容的提问来源于stack exchange,提问作者Karthikeyan Amaresan
相关产品推荐
相关产品推荐

