Elasticsearch 7.x 自定义分析器配置失败:long类型字段设置analyzer引发映射解析异常
Elasticsearch 7.x 自定义分析器配置失败:long类型字段设置analyzer引发映射解析异常
嗨,我来帮你排查这个问题~你遇到的mapper_parsing_exception本质原因很明确:Elasticsearch里的数值类型(比如你用的long)是不支持设置analyzer参数的。分析器是专门给文本类字段(text、keyword这类)设计的,用来做分词、字符过滤等文本处理;而数值类型字段直接存储原始数值,根本不会走分词/分析流程,所以你给numvalue(long类型)加analyzer就触发了语法错误。
接下来结合你的需求(前端取带符号的原始手机号,后端用纯数字long做范围搜索),给你两个可行的解决方案:
方案一:使用Ingest Pipeline预处理数据(推荐,查询效率更高)
这个方案是在数据写入Elasticsearch时就完成手机号清洗和类型转换,直接把纯数字存储为long类型:
- 先创建一个预处理管道,负责提取手机号里的纯数字并转成long:
PUT _ingest/pipeline/phone_cleanup_pipeline { "description": "清洗手机号,提取纯数字并转换为long类型", "processors": [ { "gsub": { "field": "phoneNumber", "target_field": "phoneNumber.numvalue", "pattern": "[^0-9]", "replacement": "" } }, { "convert": { "field": "phoneNumber.numvalue", "type": "long", "ignore_missing": true } } ] }
- 创建索引时,只需要定义基础的字段映射(不需要给long加分析器):
PUT my_index { "mappings": { "properties": { "phoneNumber": { "type": "keyword", "fields": { "numvalue": { "type": "long" } } } } } }
- 写入数据时指定使用这个预处理管道:
PUT my_index/_doc/1?pipeline=phone_cleanup_pipeline { "phoneNumber": "+1-800-555-1234" }
这样操作后,phoneNumber会保留原始带符号的手机号,phoneNumber.numvalue就是纯数字的long类型,直接支持范围搜索。
方案二:使用Runtime Field(适合不想修改写入流程的场景)
如果不想调整数据写入的流程,可以用Runtime Field在查询时动态计算纯数字的long值:
PUT my_index { "mappings": { "properties": { "phoneNumber": { "type": "keyword" } }, "runtime": { "phoneNumber.numvalue": { "type": "long", "script": { "source": "emit(Long.parseLong(/[^0-9]+/.matcher(doc['phoneNumber'].value).replaceAll('')))" } } } } }
查询时直接用phoneNumber.numvalue做范围搜索即可,不过这个方案是每次查询时动态计算,数据量大的话性能会比预处理管道差一些。
另外补充一下:你原来定义的phone_analyzer字符过滤逻辑是对的,但它只能用在文本类型字段上,不能直接套在long类型上,所以把这个清洗逻辑转移到上面两种方案里就可以实现你的需求啦。
备注:内容来源于stack exchange,提问作者user3822558
相关产品推荐
相关产品推荐

