一、简介

在ElasticSearch里没有专门的数组类型,任何一个字段都可以有零个和多个值。当字段值的个数大于1时,字段类型就变成了数组。

下面以视频数据为例,介绍ElasticSearch如何索引数组数据,以及如何检索数组中的字段值。

测试视频数据格式如下:

{
"media_id": 88992211,
"tags": ["电影","科技","恐怖","电竞"]
}

media_id代表视频id,tags是视频的标签,有多个值。业务上需要按视频标签检索标签下所有的视频。同一个视频有多个标签。

演示使用的ElasticSearch集群的版本是7.6.2。

二、测试演示

2.1 创建索引

PUT test_arrays
{
"settings": {
"number_of_shards": 1
},
"mappings": {
"properties": {
"media_id": {
"type": "long"
},
"tags": {
"type": "text"
}
}
}
}

2.2 向test_arrays索引里写入测试数据

POST test_arrays/_doc
{
"media_id": 887722,
"tags": [
"电影",
"科技",
"恐怖",
"电竞"
]
}

2.3 查看test_arrays内部如何索引tags字段

{
"tokens" : [
{
"token" : "电",
"start_offset" : 0,
"end_offset" : 1,
"type" : "<IDEOGRAPHIC>",
"position" : 0
},
{
"token" : "影",
"start_offset" : 1,
"end_offset" : 2,
"type" : "<IDEOGRAPHIC>",
"position" : 1
},
{
"token" : "科",
"start_offset" : 3,
"end_offset" : 4,
"type" : "<IDEOGRAPHIC>",
"position" : 102
},
{
"token" : "技",
"start_offset" : 4,
"end_offset" : 5,
"type" : "<IDEOGRAPHIC>",
"position" : 103
},
{
"token" : "恐",
"start_offset" : 6,
"end_offset" : 7,
"type" : "<IDEOGRAPHIC>",
"position" : 204
},
{
"token" : "怖",
"start_offset" : 7,
"end_offset" : 8,
"type" : "<IDEOGRAPHIC>",
"position" : 205
},
{
"token" : "电",
"start_offset" : 9,
"end_offset" : 10,
"type" : "<IDEOGRAPHIC>",
"position" : 306
},
{
"token" : "竞",
"start_offset" : 10,
"end_offset" : 11,
"type" : "<IDEOGRAPHIC>",
"position" : 307
}
]
}

从响应结果可以看到,tags数组中的每个值被分词成多个token。

2.4 检索tags数组中的值

POST test_arrays/_search
{
"query": {
"match": {
"tags": "电影"
}
}
}
响应结果:
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 0.68324494,
"hits" : [
{
"_index" : "test_arrays",
"_type" : "_doc",
"_id" : "MyhnpXQBGXOapfjvSpOW",
"_score" : 0.68324494,
"_source" : {
"media_id" : 887722,
"tags" : [
"电影",
"科技",
"恐怖",
"电竞"
]
}
}
]
}
} 模糊检索:
POST test_arrays/_search
{
"query": {
"match": {
"tags": "影"
}
}
}
响应结果
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 0.2876821,
"hits" : [
{
"_index" : "test_arrays",
"_type" : "_doc",
"_id" : "MyhnpXQBGXOapfjvSpOW",
"_score" : 0.2876821,
"_source" : {
"media_id" : 887722,
"tags" : [
"电影",
"科技",
"恐怖",
"电竞"
]
}
}
]
}
}

视频数据业务上需要通过标签精确匹配,查询标签下的所有视频。实现这种效果,需要把tags字段类型修改为keyword。test_arrays索引的mappings设置如下:

PUT test_arrays
{
"settings": {
"number_of_shards": 1
},
"mappings": {
"properties": {
"media_id": {
"type": "long"
},
"tags": {
"type": "keyword"
}
}
}
}

此时tags字段数组中每一个值对应一个token,可以实现按标签精准查询标签下视频的效果。

{
"tokens" : [
{
"token" : "电影",
"start_offset" : 0,
"end_offset" : 2,
"type" : "word",
"position" : 0
},
{
"token" : "科技",
"start_offset" : 3,
"end_offset" : 5,
"type" : "word",
"position" : 1
},
{
"token" : "恐怖",
"start_offset" : 6,
"end_offset" : 8,
"type" : "word",
"position" : 2
},
{
"token" : "电竞",
"start_offset" : 9,
"end_offset" : 11,
"type" : "word",
"position" : 3
}
]
}

实际业务场景中,视频标签的数据可能不是按数组存储的,全部标签存储在一个字符串中,标签之间用逗号分隔。

{
"media_id": 88992211,
"tags": "电影,科技,恐怖,电竞"
}

上面的标签存储格式,通过调整索引字段的类型,同样可以实现精准检索单个标签下视频的效果。test_arrays索引的配置如下:

PUT test_arrays
{
"settings": {
"number_of_shards": 1,
"analysis" : {
"analyzer" : {
"comma_analyzer": {
"tokenizer": "comma_tokenizer"
}
},
"tokenizer" : {
"comma_tokenizer": {
"type": "simple_pattern_split",
"pattern": ","
}
}
}
},
"mappings": {
"properties": {
"media_id": {
"type": "long"
},
"tags": {
"search_analyzer" : "simple",
"analyzer" : "comma_analyzer",
"type" : "text"
}
}
}
}

写入一条测试数据到test_arrays索引

POST test_arrays/_doc
{
"media_id": 887722,
"tags": "电影,科技,恐怖,电竞"
}

tags字段的索引结构如下,同样实现了一个标签对应一个token。

{
"tokens" : [
{
"token" : "电影",
"start_offset" : 0,
"end_offset" : 2,
"type" : "word",
"position" : 0
},
{
"token" : "科技",
"start_offset" : 3,
"end_offset" : 5,
"type" : "word",
"position" : 1
},
{
"token" : "恐怖",
"start_offset" : 6,
"end_offset" : 8,
"type" : "word",
"position" : 2
},
{
"token" : "电竞",
"start_offset" : 9,
"end_offset" : 11,
"type" : "word",
"position" : 3
}
]
}

通过标签精准匹配查询。

请求参数
POST test_arrays/_search
{
"query": {
"match": {
"tags": "电影"
}
}
}
响应结果
{
"took" : 6,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 0.2876821,
"hits" : [
{
"_index" : "test_arrays",
"_type" : "_doc",
"_id" : "3i2ipXQBGXOapfjv3THH",
"_score" : 0.2876821,
"_source" : {
"media_id" : 887722,
"tags" : "电影,科技,恐怖,电竞"
}
}
]
}
}

三、总结

ElasticSearch采用的一种数据类型同时支持单值和多值的设计理念,即简化了数据类型的总量,同时也降低索引配置的复杂度,是一种非常优秀的设计。

同时标签数据的组织方式支持数组和分隔符分隔两种形式,体现了ElasticSearch功能的灵活性。

数组如何在ElasticSearch中索引的更多相关文章

  1. 为何在查询中索引未被使用 (Doc ID 1549181.1)

        To Bottom * 为何在查询中索引未被使用 (Doc ID 1549181.1) To Bottom 文档内容 用途   排错步骤   高速检查   表上是否存在索引?   索引是否应该 ...

  2. 如何在Elasticsearch中安装中文分词器(IK+pinyin)

    如果直接使用Elasticsearch的朋友在处理中文内容的搜索时,肯定会遇到很尴尬的问题--中文词语被分成了一个一个的汉字,当用Kibana作图的时候,按照term来分组,结果一个汉字被分成了一组. ...

  3. 如何在Elasticsearch中解析未分配的分片(unassigned shards)

    一.精确定位到有问题的shards 1.查看哪些分片未被分配 curl -XGET localhost:9200/_cat/shards?h=index,shard,prirep,state,unas ...

  4. 更改elasticsearch中索引的mapping

    文章转载自:https://www.cnblogs.com/uglyliu/p/12331964.html 昨天研发说在kibana中统计userid字段不出图,后来查到该字段显示冲突了,然后再查看了 ...

  5. 如何在elasticsearch中查看Logstash打到elasticsearch的数据

    # cat syslog02.conf #filename:syslog02.conf #注意这个是要用#号注释掉 input{ file{ path => ["/var/log/*. ...

  6. 如何在Elasticsearch中安装中文分词器(IK)和拼音分词器?

    声明:我使用的Elasticsearch的版本是5.4.0,安装分词器前请先安装maven 一:安装maven https://github.com/apache/maven 说明: 安装maven需 ...

  7. 如何在Elasticsearch中使用pipeline API来对事件进行处理

    一个processor就像是Logstash里的一个filter pipeline是一组processor

  8. 如何在python中使用Elasticsearch

    什么是 Elasticsearch ​ 想查数据就免不了搜索,搜索就离不开搜索引擎,百度.谷歌都是一个非常庞大复杂的搜索引擎,他们几乎索引了互联网上开放的所有网页和数据.然而对于我们自己的业务数据来说 ...

  9. Elasticsearch 中为什么选择倒排索引而不选择 B 树索引

    目录 前言 为什么全文索引不使用 B+ 树进行存储 全文检索 正排索引 倒排索引 倒排索引如何存储数据 FOR 压缩 RBM 压缩 倒排索引如何存储 字典树(Tria Tree) FST FSM 构建 ...

随机推荐

  1. Markdown实验样例

    一级标题 二级标题 三级标题 重新开始一个段落 这是新的段落 斜体文本 粗体文本 粗斜体文本 下面是分隔线 删除线 下划线 脚注[1] 无序列表 第一项 嵌套元素1 嵌套元素2 第二项 嵌套元素1 嵌 ...

  2. VUE 中引入百度地图(vue-Baidu-Map)

    1.安装 $ npm install vue-baidu-map --save 2.全局注册,在main.js中引入以下代码 import BaiduMap from 'vue-baidu-map' ...

  3. C++ Templates (1.4 默认模板实参 Default Template Arguments)

    返回完整目录 目录 1.4 默认模板实参 Default Template Arguments 1.4 默认模板实参 Default Template Arguments 可以为模板参数定义默认值,这 ...

  4. linux tmpfs及消耗内存脚本

    一.tmpfs介绍 tmpfs是一种虚拟内存文件系统,正如这个定义它最大的特点就是它的存储空间在VM里面VM是由linux内核里面的vm子系统管理的东西,现在大多数操作系统都采用了虚拟内存管理机制VM ...

  5. SuperSlide轮播切换

    <!-- 点击切换引入 --> <script type="text/javascript" src="js/jquery.js">&l ...

  6. python的各种包安装地址

    http://www.lfd.uci.edu/~gohlke/pythonlibs/#scipy-stack 这个网页里有python的所有包,whl的后缀是python压缩包的意思.在windows ...

  7. Java动态代理(三)——Cglib动态代理

    一.Cglib动态代理Cglib是一个优秀的动态代理框架,它的底层使用ASM在内存中动态的生成被代理类的子类,使用Cglib即使代理类没有实现任何接口也可以实现动态代理功能.而且,它的运行速度要远远快 ...

  8. Black & White(尺取)

    链接:https://ac.nowcoder.com/acm/contest/893/F来源:牛客网 * 第一行一个整数 T ,表示接下来有 T 个样例.* 首先输入n,m,表示S串的长度n和操作次数 ...

  9. 一文读懂神经网络训练中的Batch Size,Epoch,Iteration

    一文读懂神经网络训练中的Batch Size,Epoch,Iteration 作为在各种神经网络训练时都无法避免的几个名词,本文将全面解析他们的含义和关系. 1. Batch Size 释义:批大小, ...

  10. basicInterpreter1.02 增加对for循环的支持

    源码下载:https://files.cnblogs.com/files/heyang78/basicInterpreter102-20200531-2.rar 输入: for x= to print ...