《Elastic Stack 实战手册》——三、产品能力——3.4.入门篇——3.4.2.Elasticsearch基础应用——3.4.2.17.Text analysis, settings 及 mappings——3.4.2.17.4.Analyzers / Custom analyzers(14) https://developer.aliyun.com/article/1229755
身份证号分词示例
在本例中我们要实现通过输入员工的身份证号匹配员工信息。输入时除了支持整体匹配以外同时还要支持使用部分内容的模糊匹配如:出生日期/身份证号后八位/后六位/后四位等关键信息。索引包含以下四个字段:
l ID 文本类型,身份证号,需要分词器实现模糊匹配。
l emplyee_name 文本类型,员工姓名。
l dept 文本类型,所在部门。
l mobile 文本类型,联系方式。
模糊匹配要想实现身份证号信息提取,首先需要了解一下身份证号的信息规则:二代身份证号长度为18位,其中前六位中每两位分别表示签发的省市区的行政规划代码,7-14位表示出生年月日,15-16位表示派出所代码,17位标识性别,奇数为男性,偶数为女性,而最后一位是用于校验信息的校验码由0-9或X组成。按本例中的要求创建的自定义分词器需要满足一个身份证号处理后能提取到整体(1-18位),出生年月(7-14位),后八位(11-18位),后六位(14-18位),后四位(15-18位)五种场景。直接使用 Tokenizer 按照位置切分目前在 Elasticsearch 中没有满足需求的组件,所以就需要考虑一下身份证号在切分前进行变形。我们可以在
Char_Filter 阶段使用 pattern_replace 将身份证号按照规则将内容提取后使用空格追加到原有身份证号的后面,如 “110102199007050722” 处理后会变成 “110102199007050722 19900705 07050722 050722 0722”,然后再使用空格切分即可。分词器 ID_analyzer 结构如下:
l Char Filter
○ Pattern Replace Filter,匹配到的内容进行替换
l Tokenizer
○ whitespace Tokenizer
l Token Filter
○ Lowercase Token Filter,单词转换为小写字母统一格式
定义正则表达式 (\d{6})(\d{4})(\d{2})(\d{2})([\dxX]{4}) 把字符串按照位置进行了一个分组,这样就可以在 replacement 中按照分组标签来进行字符串拼接。和上一例一样,在搜索时需要将输入的内容当作整体来匹配不进行提取替换操作,其它设置和写入分词器保持一致,分词器 ID_
search 结构如下:
l Tokenizer
○ whitespace Tokenizer
l Token Filter
○ Lowercase Token Filter,单词转换为小写字母统一格式
PUT employee_info { "settings": { "analysis": { "analyzer": { "ID_analyzer": { "type": "custom", "char_filter": [ "ID_char_filter ], "tokenizer": "whitespace", "filter": [ "lowercase" ] }, "ID_search": { "type": "custom", "tokenizer": "whitespace", "filter": [ "lowercase" ] } }, "char_filter": { "ID_char_filter": { "type": "pattern_replace", "pattern": """(\d{6})(\d{4})(\d{2})(\d{2})([\dxX]{4})""", "replacement": "$0 $2$3$4 $3$4$5 $4$5 $5" } } } }, "mappings": { "properties": { "ID": { "type": "text", "analyzer": "ID_analyzer", "search_analyzer": "ID_search" }, "employee_name":{ "type": "text" }, "dept": { "type": "keyword" }, "mobile":{ "type": "keyword" } } } } POST _bulk {"index":{"_index":"employee_info","_id": "1"}} {"employee_name":"符杰","ID":"110102199007050722","dept":"IT","mobile":"13853411491"} {"index":{"_index":"employee_info","_id": "2"}} {"employee_name":"熊志胜","ID":"130102198610211600","dept":"BU","mobile":"13758526665"} {"index":{"_index":"employee_info","_id": "3"}} {"employee_name":"安晨龙","ID":"143105199605078636","dept":"IT","mobile":"16602029900"} {"index":{"_index":"employee_info","_id": "4"}} {"employee_name":"尚静","ID":"110105198807206667","dept":"HR","mobile":"15170488414"} {"index":{"_index":"employee_info","_id": "5"}} {"employee_name":"邹松彬","ID":"22010219830713347X","dept":"LAW","mobile":"18741918417"}
查询测试数据生日为 19900705 或后四位是 347x 的员工信息,都能返回查询结果。
GET employee_info/_search { "query": { "match": { "ID": "19900705 347x" } }