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
















