Elasticsearch 有没有数组类型?有哪些坑?
近期 Elasticsearch 数组问题被问到的比较多,为了方便大家对数组建立全局认知,我把数组相关实战问题梳理出来,让更多后来人遇到类似问题少走不必要的弯路。
精简几个核心问题列举如下:
• Elasticsearch 是否有数组类型?Elasticsearch 数据选型有没有坑?
• Elasticsearch 如何获取数组中第i号位置的值?
• Elasticsearch 如何获取数组最后一个元素的值?
了解 Elasticsearch 版本历史的读者会知道 1.X 版本中没有独立模块强调数组 Array 类型。
Elasticsearch 2.X 版本之后,数组类型才单独被拎出来。
在 Elasticsearch 中,没有专门的数组数据类型。默认情况下,任何字段都可以包含零个或多个值,但是,数组中的所有值必须具有相同的数据类型。什么意思呢?
• long 类型存储一个值是long类型,存储多个自然就成为 long 数组类型;
• keyword 类型存储一个值是 keyword 类型,存储多个值就成为 keyword 数组类型。
实战一把:
如上示例,可以更加清晰的看出,当我们选型使用数组时,和平时 Mapping 设置类型一样,不需要额外的修改 Mapping 任何内容,只需要导入相同数据类型的数据即可。
这时候,读者可能会问,我不小心写入了不同类型的数据咋办?
继续实战一把,探个究竟。
由于 Elasticsearch 做了弱类型匹配校验检查,导致数据依然可以写入,我们肉眼看到的整形类型,实际本质存储为keyword 类型,这也是为什么“22222”能被检索召回的原因。
3.1 动态导入数组类型数据,第一次写入数据的类型决定了数组的类型。
如上,写入的是 long 类型的数组。long 咋来的,动态类型匹配 date_detection 得到的!
https://www.elastic.co/guide/en/elasticsearch/reference/current/dynamic-mapping.html
3.2 不能独立的检索数组中的单个字段
如下示例,即便仅检索“basketball”不能独立只召回“basketball”,数组数据会一起返回。
如果非要实现单独召回数据,需要借助:nested 嵌套类型实现。
举例,仅检索召回 “basketball”,需要借助 script_field 或者 runtime field 实现。
实现参考如下:
注意:存储数组数据顺序是:
如上示例中的2,可以换成:0,1,2,3。
召回结果如下:
后台按照字母顺序做了处理,返回结果数据。
也就是说:我们以脚本的方式无法精准获取对应位次上的数据。
这块目前看,没有最优的获取方式。如果大家有,欢迎留言交流。
通过 ingest pipeline 预处理方式实现如下:
中间核心脚本不是最优实现方式,欢迎大家留言反馈精简处理方式。
• 第一步:数组转 list;
• 第二步:取 list 最后一个元素值,结果仍然为 list;
• 第三步:list 转 string;
• 第四步:string 取核心元素,去头、去尾。
• 第五步:将中间结果赋值给新字段。
返回结果如下:
上面的预处理方式对数组而言,也是仅适用于获取特定值的场景。
Elasticsearch 数组选型需要结合业务场景需要。
数据相关的问题还有很多很多,比如:
1.数组高亮问题
2.数组聚合问题
3.数组召回数据问题
4......
大家在选型或者实践的过程中,如果涉及大量脚本的时候,要多考虑能否通过写入前 ingest 预处理方式。本质是:以空间换时间,最大化提升检索效率。
欢迎大家就数组问题留言讨论。
1、重磅 | 死磕 Elasticsearch 方法论认知清单(2021年国庆更新版)
2、Elasticsearch 7.X 进阶实战私训课(口碑不错)
公众号:铭毅天下Elasticsearch