草庐IT

ElasticSearch学习随笔之嵌套操作

YPhen 2023-08-15 原文

ElasticSearch

1、ElasticSearch学习随笔之基础介绍
2、ElasticSearch学习随笔之简单操作
3、ElasticSearch学习随笔之java api 操作
4、ElasticSearch学习随笔之SpringBoot Starter 操作
5、ElasticSearch学习随笔之嵌套操作

ElasticSearch,创始人 Shay Banon(谢巴农)
本文主要讲解ElasticSearch 基础操作,Kibana 以及 java api 调用操作。


文章目录


前言

今天工作中遇到嵌套类型的数据,查询总是查询不到,一开始感到疑惑,为啥 match_all 的时候有,但是精确操作就查不到,查了半天才发现,嵌套操作有点区别。
本文主要对ElasticSearch嵌套(Nested) 操作,以便上手 用 ElasticSearch

一、嵌套数据类型

在基础篇中介绍了一些 ES 的数据类型,比如:Text、keyword、byte、string 等,这些类型的数据操作起来比较容易,在 ES简单操作中介绍了,不过 ES 有些数据结构上稍微复杂一点,使用嵌套类型就比较明显和容易维护。
比如说一个子弹是 productName ,但是这个字段有中英文、id、raw等不同的值,如果这些字段用 string 类型存储,那字段就会很多,那么我们可以用嵌套类型的数据结构,这样维护起来就方便点,不过需要用嵌套的方式进行查询。
类似这样:

{
	"productName":{
		"cn":"手机",
		"en":"iphone",
		"id": 100,
		"raw":"苹果手机"
	}
}

二、添加数据

2.1 构建嵌套 mapping 映射

下面的 mapping 映射中,相当于 solr 的schema 定义固定的数据结构,我们也可以增加其他数据类型,不过在创建了映射之后就只能按照 mapping 来存放数据和操作。
productName 一个嵌套(nested)类型来存放的,在查询,排序等操作的时候就需要按照嵌套来操作。

PUT productinfo
{
  "mappings": {
    "properties": {
      "productName":{
        "type": "nested",
        "properties": {
          "cn":{
            "type":"keyword",
            "store":true
          },
          "en":{
            "type":"keyword",
            "store":true
          },
          "raw":{
            "type":"keyword",
            "store":true
          },
          "id":{
            "type":"keyword",
            "store":true
          }
        }
      },
      "productSize":{
        "type": "keyword",
        "store": true
      },
      "productDesc":{
        "type": "text",
        "store": true
      }
    }
  }
}

2.2 添加测试数据

我们用 bulk 来批量添加数据,按照 mapping 添加数据。

POST productinfo/_bulk
{"index":{"_index":"productinfo"}}
{"productName":{"cn":"苹果手机11","en":"iphone11","id":"1001","raw":"手机"},"productSize":16,"productDesc":"打电话,微信,拍照"}
{"index":{"_index":"productinfo"}}
{"productName":{"cn":"苹果手机12","en":"iphone12","id":"1002","raw":"手机"},"productSize":17,"productDesc":"打电话,微信,拍照3000像素"}
{"index":{"_index":"productinfo"}}
{"productName":{"cn":"小米手机","en":"xiaomi","id":"1003","raw":"手机"},"productSize":15,"productDesc":"打电话,微信,拍照,5G上网"}
{"index":{"_index":"productinfo"}}
{"productName":{"cn":"华为手机","en":"huawei","id":"1004","raw":"手机"},"productSize":14,"productDesc":"打电话,微信,拍照,打游戏"}

2.3 添加mapping之外的数据

也可以添加没有 mapping 的字段,比如 commonProductName 就没有 mapping,不过查询操作也不用按照嵌套来查询。

{"index":{"_index":"productinfo"}}
{"commonProductName":"笔记本电脑","productSize":14,"productDesc":"上网,工作,打游戏,学习,看电影"}
{"index":{"_index":"productinfo"}}
{"commonProductName":"液晶屏电视","productSize":60,"productDesc":"上网,看电影,追剧"}

2.4 查看添加的数据

用 match_all 来查看全部的数据。
这里有个不同之处,就是 es7 之前的版本,需要指定 dataType 类型,就像在 es 基础操作篇(见文档开头)那样,因为 基础篇是用 6.x 的版本写的。

三、嵌套操作

3.1 按照嵌套类型查询

说明:在搜索嵌套类型的字段的时候,需要指定 path 参数,来告诉 es 从 productName 字段下的 内嵌字段用 match、term、multi_match 等来搜索。
比如说现在要按照 productName 来搜索一个产品,搜索 “华为手机” 库里面有几个,搜索如下:

POST productinfo/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "nested": {
            "path": "productName",
            "query": {
              "bool": {
                "should": [
                  {
                    "match": {
                      "productName.cn": "华为手机"
                    }
                  }
                ]
              }
            }
          }
        }
      ]
    }
  }
}

搜索结果:

从搜索结果可以看到,进准搜索到了华为手机这个产品,当然,也可以模糊查询, 就像 es 操作的基础篇那样 (见文档开头系列目录),或者搜索 cn , en 另个字段,那么外面就是 should (or) 的关系 。

3.2 按照嵌套类型排序

下面按照 productName.cn 进行模糊搜索出来了两条数据,然后按照 productName.id 降序排序。

POST productinfo/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "nested": {
            "path": "productName",
            "query": {
              "bool": {
                "should": [
                  {
                    "wildcard": {
                      "productName.cn": "*苹果*"
                    }
                  }
                ]
              }
            }
          }
        }
      ]
    }
  },
  "sort": [
    {
      "productName.id": {
        "order": "desc",
        "nested_path": "productName"
      }
    }
  ]
}

排序结果如下:

注意:es 提示了一行红字,意思是说 nested_path 已经弃用了,被 nested 替代了,不过我感觉还是用起来挺方便的。

那么官方推荐应该怎么写呢?如下:
下面的写法基本不变,不过坑的就是,nested 居然不提示,但是生效

POST productinfo/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "nested": {
            "path": "productName",
            "query": {
              "bool": {
                "should": [
                  {
                    "wildcard": {
                      "productName.cn": "*苹果*"
                    }
                  }
                ]
              }
            }
          }
        }
      ]
    }
  },
  "sort": [
    {
      "productName.id": {
        "order": "desc",
        "nested":{
          "path":"productName"
        }
      }
    }
  ]
}

3.3 嵌套类型分组统计

按照 productName 和 productName.cn 进行分组统计,如下:

POST productinfo/_search
{
  "query": {
    "match_all": {}
  },
  "aggs": {
    "productName_count": {
      "nested": {
        "path": "productName"
      },
      "aggs": {
        "cn_count": {
          "terms": {
            "field": "productName.cn",
            "size": 10
          }
        }
      }
    }
  }
}

执行结果如下:

统计出来,productName.cn 字段,有 3 个苹果11, 华为、小米、苹果12 各 1个。


更复杂的分组统计可到官网查看,工作中大部分用到的以上的风阻统计就可以满足了,若有更复杂的,则继续在及过上过滤和统计。

3.4 修改嵌套类型字段值

修改按照 PUT 操作,带上 _id 即可修改。

PUT productinfo/_bulk
{"index":{"_index":"productinfo", "_id":"ZU8ga4MBZkN8aRGpIqAA"}}
{"productName":{"cn":"苹果手机12","en":"iphone11","id":"1008","raw":"手机"},"productSize":16,"productDesc":"打电话,微信,拍照"}

修改结果:

四、总结

ElasticSearch 现在比较流行的全文搜索引擎,平时工作中用到的都是基础类型,有些情况下用到了嵌套类型字段,虽然数据在架构师清晰了,但是操作起来变的稍微复杂点,看情况使用吧。

有关ElasticSearch学习随笔之嵌套操作的更多相关文章

  1. ruby-on-rails - Rails 编辑表单不显示嵌套项 - 2

    我得到了一个包含嵌套链接的表单。编辑时链接字段为空的问题。这是我的表格:Editingkategori{:action=>'update',:id=>@konkurrancer.id})do|f|%>'Trackingurl',:style=>'width:500;'%>'Editkonkurrence'%>|我的konkurrencer模型:has_one:link我的链接模型:classLink我的konkurrancer编辑操作:defedit@konkurrancer=Konkurrancer.find(params[:id])@konkurrancer.link_attrib

  2. ruby - 将散列转换为嵌套散列 - 2

    这道题是thisquestion的逆题.给定一个散列,每个键都有一个数组,例如{[:a,:b,:c]=>1,[:a,:b,:d]=>2,[:a,:e]=>3,[:f]=>4,}将其转换为嵌套哈希的最佳方法是什么{:a=>{:b=>{:c=>1,:d=>2},:e=>3,},:f=>4,} 最佳答案 这是一个迭代的解决方案,递归的解决方案留给读者作为练习:defconvert(h={})ret={}h.eachdo|k,v|node=retk[0..-2].each{|x|node[x]||={};node=node[x]}node[

  3. Ruby——嵌套类和子类是一回事吗? - 2

    下面例子中的Nested和Child有什么区别?是否只是同一事物的不同语法?classParentclassNested...endendclassChild 最佳答案 不,它们是不同的。嵌套:Computer之外的“Processor”类只能作为Computer::Processor访问。嵌套为内部类(namespace)提供上下文。对于ruby​​解释器Computer和Computer::Processor只是两个独立的类。classComputerclassProcessor#Tocreateanobjectforthisc

  4. ruby - 模块嵌套代码风格偏好 - 2

    我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的

  5. ruby-on-rails - 使用回形针的嵌套形式 - 2

    我有一个名为posts的模型,它有很多附件。附件模型使用回形针。我制作了一个用于创建附件的独立模型,效果很好,这是此处说明的View(https://github.com/thoughtbot/paperclip):@attachment,:html=>{:multipart=>true}do|form|%>posts中的嵌套表单如下所示:prohibitedthispostfrombeingsaved:@attachment,:html=>{:multipart=>true}do|at_form|%>附件记录已创建,但它是空的。文件未上传。同时,帖子已成功创建...有什么想法吗?

  6. ruby-on-rails - Rails 3,嵌套资源,没有路由匹配 [PUT] - 2

    我真的为这个而疯狂。我一直在搜索答案并尝试我找到的所有内容,包括相关问题和stackoverflow上的答案,但仍然无法正常工作。我正在使用嵌套资源,但无法使表单正常工作。我总是遇到错误,例如没有路线匹配[PUT]"/galleries/1/photos"表格在这里:/galleries/1/photos/1/edit路线.rbresources:galleriesdoresources:photosendresources:galleriesresources:photos照片Controller.rbdefnew@gallery=Gallery.find(params[:galle

  7. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

  8. CAN协议的学习与理解 - 2

    最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总

  9. 深度学习部署:Windows安装pycocotools报错解决方法 - 2

    深度学习部署:Windows安装pycocotools报错解决方法1.pycocotools库的简介2.pycocotools安装的坑3.解决办法更多Ai资讯:公主号AiCharm本系列是作者在跑一些深度学习实例时,遇到的各种各样的问题及解决办法,希望能够帮助到大家。ERROR:Commanderroredoutwithexitstatus1:'D:\Anaconda3\python.exe'-u-c'importsys,setuptools,tokenize;sys.argv[0]='"'"'C:\\Users\\46653\\AppData\\Local\\Temp\\pip-instal

  10. ruby - 如何使用 Selenium Webdriver 根据 div 的内容执行操作? - 2

    我有一个使用SeleniumWebdriver和Nokogiri的Ruby应用程序。我想选择一个类,然后对于那个类对应的每个div,我想根据div的内容执行一个Action。例如,我正在解析以下页面:https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=puppies这是一个搜索结果页面,我正在寻找描述中包含“Adoption”一词的第一个结果。因此机器人应该寻找带有className:"result"的div,对于每个检查它的.descriptiondiv是否包含单词“adoption

随机推荐