一、简介

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

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

测试视频数据格式如下:

  1. {
  2. "media_id": 88992211,
  3. "tags": ["电影","科技","恐怖","电竞"]
  4. }

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

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

二、测试演示

2.1 创建索引

  1. PUT test_arrays
  2. {
  3. "settings": {
  4. "number_of_shards": 1
  5. },
  6. "mappings": {
  7. "properties": {
  8. "media_id": {
  9. "type": "long"
  10. },
  11. "tags": {
  12. "type": "text"
  13. }
  14. }
  15. }
  16. }

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

  1. POST test_arrays/_doc
  2. {
  3. "media_id": 887722,
  4. "tags": [
  5. "电影",
  6. "科技",
  7. "恐怖",
  8. "电竞"
  9. ]
  10. }

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

  1. {
  2. "tokens" : [
  3. {
  4. "token" : "电",
  5. "start_offset" : 0,
  6. "end_offset" : 1,
  7. "type" : "<IDEOGRAPHIC>",
  8. "position" : 0
  9. },
  10. {
  11. "token" : "影",
  12. "start_offset" : 1,
  13. "end_offset" : 2,
  14. "type" : "<IDEOGRAPHIC>",
  15. "position" : 1
  16. },
  17. {
  18. "token" : "科",
  19. "start_offset" : 3,
  20. "end_offset" : 4,
  21. "type" : "<IDEOGRAPHIC>",
  22. "position" : 102
  23. },
  24. {
  25. "token" : "技",
  26. "start_offset" : 4,
  27. "end_offset" : 5,
  28. "type" : "<IDEOGRAPHIC>",
  29. "position" : 103
  30. },
  31. {
  32. "token" : "恐",
  33. "start_offset" : 6,
  34. "end_offset" : 7,
  35. "type" : "<IDEOGRAPHIC>",
  36. "position" : 204
  37. },
  38. {
  39. "token" : "怖",
  40. "start_offset" : 7,
  41. "end_offset" : 8,
  42. "type" : "<IDEOGRAPHIC>",
  43. "position" : 205
  44. },
  45. {
  46. "token" : "电",
  47. "start_offset" : 9,
  48. "end_offset" : 10,
  49. "type" : "<IDEOGRAPHIC>",
  50. "position" : 306
  51. },
  52. {
  53. "token" : "竞",
  54. "start_offset" : 10,
  55. "end_offset" : 11,
  56. "type" : "<IDEOGRAPHIC>",
  57. "position" : 307
  58. }
  59. ]
  60. }

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

2.4 检索tags数组中的值

  1. POST test_arrays/_search
  2. {
  3. "query": {
  4. "match": {
  5. "tags": "电影"
  6. }
  7. }
  8. }
  9. 响应结果:
  10. {
  11. "took" : 1,
  12. "timed_out" : false,
  13. "_shards" : {
  14. "total" : 1,
  15. "successful" : 1,
  16. "skipped" : 0,
  17. "failed" : 0
  18. },
  19. "hits" : {
  20. "total" : {
  21. "value" : 1,
  22. "relation" : "eq"
  23. },
  24. "max_score" : 0.68324494,
  25. "hits" : [
  26. {
  27. "_index" : "test_arrays",
  28. "_type" : "_doc",
  29. "_id" : "MyhnpXQBGXOapfjvSpOW",
  30. "_score" : 0.68324494,
  31. "_source" : {
  32. "media_id" : 887722,
  33. "tags" : [
  34. "电影",
  35. "科技",
  36. "恐怖",
  37. "电竞"
  38. ]
  39. }
  40. }
  41. ]
  42. }
  43. }
  44. 模糊检索:
  45. POST test_arrays/_search
  46. {
  47. "query": {
  48. "match": {
  49. "tags": "影"
  50. }
  51. }
  52. }
  53. 响应结果
  54. {
  55. "took" : 1,
  56. "timed_out" : false,
  57. "_shards" : {
  58. "total" : 1,
  59. "successful" : 1,
  60. "skipped" : 0,
  61. "failed" : 0
  62. },
  63. "hits" : {
  64. "total" : {
  65. "value" : 1,
  66. "relation" : "eq"
  67. },
  68. "max_score" : 0.2876821,
  69. "hits" : [
  70. {
  71. "_index" : "test_arrays",
  72. "_type" : "_doc",
  73. "_id" : "MyhnpXQBGXOapfjvSpOW",
  74. "_score" : 0.2876821,
  75. "_source" : {
  76. "media_id" : 887722,
  77. "tags" : [
  78. "电影",
  79. "科技",
  80. "恐怖",
  81. "电竞"
  82. ]
  83. }
  84. }
  85. ]
  86. }
  87. }

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

  1. PUT test_arrays
  2. {
  3. "settings": {
  4. "number_of_shards": 1
  5. },
  6. "mappings": {
  7. "properties": {
  8. "media_id": {
  9. "type": "long"
  10. },
  11. "tags": {
  12. "type": "keyword"
  13. }
  14. }
  15. }
  16. }

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

  1. {
  2. "tokens" : [
  3. {
  4. "token" : "电影",
  5. "start_offset" : 0,
  6. "end_offset" : 2,
  7. "type" : "word",
  8. "position" : 0
  9. },
  10. {
  11. "token" : "科技",
  12. "start_offset" : 3,
  13. "end_offset" : 5,
  14. "type" : "word",
  15. "position" : 1
  16. },
  17. {
  18. "token" : "恐怖",
  19. "start_offset" : 6,
  20. "end_offset" : 8,
  21. "type" : "word",
  22. "position" : 2
  23. },
  24. {
  25. "token" : "电竞",
  26. "start_offset" : 9,
  27. "end_offset" : 11,
  28. "type" : "word",
  29. "position" : 3
  30. }
  31. ]
  32. }

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

  1. {
  2. "media_id": 88992211,
  3. "tags": "电影,科技,恐怖,电竞"
  4. }

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

  1. PUT test_arrays
  2. {
  3. "settings": {
  4. "number_of_shards": 1,
  5. "analysis" : {
  6. "analyzer" : {
  7. "comma_analyzer": {
  8. "tokenizer": "comma_tokenizer"
  9. }
  10. },
  11. "tokenizer" : {
  12. "comma_tokenizer": {
  13. "type": "simple_pattern_split",
  14. "pattern": ","
  15. }
  16. }
  17. }
  18. },
  19. "mappings": {
  20. "properties": {
  21. "media_id": {
  22. "type": "long"
  23. },
  24. "tags": {
  25. "search_analyzer" : "simple",
  26. "analyzer" : "comma_analyzer",
  27. "type" : "text"
  28. }
  29. }
  30. }
  31. }

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

  1. POST test_arrays/_doc
  2. {
  3. "media_id": 887722,
  4. "tags": "电影,科技,恐怖,电竞"
  5. }

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

  1. {
  2. "tokens" : [
  3. {
  4. "token" : "电影",
  5. "start_offset" : 0,
  6. "end_offset" : 2,
  7. "type" : "word",
  8. "position" : 0
  9. },
  10. {
  11. "token" : "科技",
  12. "start_offset" : 3,
  13. "end_offset" : 5,
  14. "type" : "word",
  15. "position" : 1
  16. },
  17. {
  18. "token" : "恐怖",
  19. "start_offset" : 6,
  20. "end_offset" : 8,
  21. "type" : "word",
  22. "position" : 2
  23. },
  24. {
  25. "token" : "电竞",
  26. "start_offset" : 9,
  27. "end_offset" : 11,
  28. "type" : "word",
  29. "position" : 3
  30. }
  31. ]
  32. }

通过标签精准匹配查询。

  1. 请求参数
  2. POST test_arrays/_search
  3. {
  4. "query": {
  5. "match": {
  6. "tags": "电影"
  7. }
  8. }
  9. }
  10. 响应结果
  11. {
  12. "took" : 6,
  13. "timed_out" : false,
  14. "_shards" : {
  15. "total" : 1,
  16. "successful" : 1,
  17. "skipped" : 0,
  18. "failed" : 0
  19. },
  20. "hits" : {
  21. "total" : {
  22. "value" : 1,
  23. "relation" : "eq"
  24. },
  25. "max_score" : 0.2876821,
  26. "hits" : [
  27. {
  28. "_index" : "test_arrays",
  29. "_type" : "_doc",
  30. "_id" : "3i2ipXQBGXOapfjv3THH",
  31. "_score" : 0.2876821,
  32. "_source" : {
  33. "media_id" : 887722,
  34. "tags" : "电影,科技,恐怖,电竞"
  35. }
  36. }
  37. ]
  38. }
  39. }

三、总结

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. springMVC入门(二)------springMVC入门案例

    简介 本案例主要完成了springMVC的基本配置,可针对响应的HTTP URL返回数据与视图 一.###web.xml的配置 要使springMVC生效,首先需要对web.xml进行配置,配置spr ...

  2. powerdesigner16.5 生成sql语句

    1.首先安装好designer. 2.打开之后新建一个project. 3.创建之后可能会生成这样的页面. 4.点击这个图标就能调出那个视图框. 5.在project处单机右键,New一个Concep ...

  3. 第5篇scrum冲刺(5.25)

    一.站立会议 1.照片 2.工作安排 成员 昨天已完成的工作 今天的工作安排 困难 陈芝敏   线下模块(还剩下获取词的数据库)  研究云开发,更新了登录模块,把用户的信息传入数据库了  起初在云函数 ...

  4. Java数据结构——AVL树

    AVL树(平衡二叉树)定义 AVL树本质上是一颗二叉查找树,但是它又具有以下特点:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树,并且拥有自平衡机制.在AV ...

  5. CSP 202006-1 线性分类器python实现

    思路 这题问题是对于这一群点和一条直线,我们也不知道直线上方的是A类还是直线下方的是A类.其实对于这个二分类问题,我们也没必要知道.我们只需要判断直线每一测的点是不是一类(A类或B类)就可以了. 至于 ...

  6. Ubuntu 20.04.1 安装软件和系统配置脚本

    #!/bin/bash # https://launchpad.net/ubuntu # https://www.easyicon.net # https://download-chromium.ap ...

  7. Git使用感悟

    前言 分支介绍 我们现在开发的分支一般是这样的(基于上面那张图片的): master:上线用的 dev:开发用的 featature_xxx:开发用的 test:测试用的 hotfix:修复bug的 ...

  8. 正则表达式断言精讲 Java语法实现

    目录 断言 1.2.3.1 情景导入 什么是断言 断言的语法规则 零宽断言为什么叫零宽断言 零宽 前行 负向 断言DEMO 断言的基础应用和实际用处 验证不包含 验证开头包含 验证开头包含且匹配到的数 ...

  9. 【Go语言入门系列】(七)如何使用Go的方法?

    [Go语言入门系列]前面的文章: [Go语言入门系列](四)之map的使用 [Go语言入门系列](五)之指针和结构体的使用 [Go语言入门系列](六)之再探函数 本文介绍Go语言的方法的使用. 1. ...

  10. day41:MYSQL:select查询练习题

    目录 1.表结构 2.创建表和插入数据 3.习题 1.表结构 2.建表和插入数据 # 创建班级表 create table class( cid int primary key auto_increm ...