6.ELK之Elasticsearch嵌套(Nested)类型

news2024/9/28 15:33:09

0、前言

在Elasticsearch实际应用中经常会遇到嵌套文档的情况,而且会有“对象数组彼此独立地进行索引和查询的诉求”。在ES中这种嵌套文档称为父子文档,父子文档“彼此独立地进行查询”至少有以下两种方式:

1)父子文档。在ES的5.x版本中通过parent-child父子type实现,即一个索引对应多个type;

对于6.X+版本由于不再支持一个索引多个type,所以父子索引的实现改成了Join。

2)Nested嵌套类型。

1、ES数据类型概览

1.常见类型
    binary:接受二进制值作为 Base64 编码的字符串。默认情况下,该字段不存储,也不可搜索,不能包含换行符 \n
    boolean:布尔类型,可以接受 true 或 false ,可以使用字符串和直接到布尔类型,空字符串为 false,包含:true,false,"true","false",""
    keyword:关键字类型,不进行分词,直接索引,支持模糊、支持精确匹配,支持聚合、排序操作,用于筛选数据。最大支持的长度为——32766 个 UTF-8 类型的字符。
    number:数字类型,文档链接
        long
        integer
        short
        byte
        double
        float
        half_float
        scaled_float
        unsigned_long

    Dates:日期类型
        date:可以是格式化后的日期字符串,也可以是时间戳,例如 2015-01-01, 2015-01-01T12:10:30Z,1420070400001
        date_nanos:支持纳秒的日期格式,在 es 内部是存的长整型
    alias :别名类型

2.对象和关系类型
    object:对象类型,是一个 json 对象
    flattened:将对象作为单个字段值存储
    nested:嵌套数据类型,可以看成是一个特殊的对象类型,可以让对象数组独立检索
    join:同一个文档,但具有父子关系的,类似于树
3.结构化数据类型
    range:范围类型,可以用来表示数据的区间
        integer_range
        float_range
        long_range
        double_range
        date_range
        ip_range

2、一个例子说明nested类型的作用

(1)Nested:嵌套对象是object数据类型的专用版本,能够对 对象数组进行彼此独立地索引和查询。

(2)对象数组默认组织形式

内部对象字段数组的实际存储机制与我们想的不一样。Lucene没有内部对象的概念,因为ElasticSearch将对象层次结构扁平化为一个字段名和字段值的列表。例如下面文档。

PUT user/user_info/1
{
  "group" : "man",
  "userName" : [ 
    {
      "first" : "张",
      "last" :  "三"
    },
    {
      "first" : "李",
      "last" :  "四"
    }
  ]
}

这里想要查询first为“张”,last为“四”的数据,按照我们的理解应该没有这种数据。按如下语句查询。

PUT user/user_info/1
{
  "group" : "human",
  "sex": "man",
  "userName" : [ 
    {
      "first" : "张",
      "last" :  "三"
    },
    {
      "first" : "李",
      "last" :  "四"
    }
  ]
}

查询结果如下:居然查询到了。这显然不符合我们的预期。

这个原因就是前面所说的lucene没有内部对象的概念,所谓的内部对象实际是被扁平化为一个简单的字段名称和值列表。文档内部存储是这个样子的:

{
  "group" :        "human",
  "sex" :          "man",
  "userName.first" : [ "张", "李" ],
  "userName.last" :  [ "三", "四" ]
}

显然 userName.first 和 userName.last 字段平面化为多值字段,之前的关联性丢失,查询就不会得到预期的结果。

那么要如何实现自己想要的语义呢? —— 显然就是本文想要说的nested了。

3、nested类型的使用

3.1、首先插入如下一条记录

其含义为博客文章信息数据,其中每篇文章的评论以comments字段数组存储。

PUT /financeblogs/blog/docidart1
{
  "title": "Invest Money",
  "body": "Please start investing money as soon...",
  "tags": ["money", "invest"],
  "published_on": "18 Oct 2017",
  "comments": [
    {
      "name": "William",
      "age": 34,
      "rating": 8,
      "comment": "Nice article..",
      "commented_on": "30 Nov 2017"
    },
    {
      "name": "John",
      "age": 38,
      "rating": 9,
      "comment": "I started investing after reading this.",
      "commented_on": "25 Nov 2017"
    },
    {
      "name": "Smith",
      "age": 33,
      "rating": 7,
      "comment": "Very good post",
      "commented_on": "20 Nov 2017"
    }
  ]
}

现在对于这条数据评论人姓名、年龄如下。

nameage
William34
John38
Smith33
3.2、非nested时内部对象无法按预期查询

我们尝试查询{name:John, age:34}评论过的博客,按照我们的理解应该没有符合条件的记录。但是由于前面说过的平铺的原因实际上如下查询语句是检索到这条数据了的。

GET /financeblogs/blog/_search
{
	"query":{
		"bool":{
			"must":[
				{
					"match":{
						"comments.name":"John"
					}
				},
				{
					"match":{
						"comments.age":"34"
					}
				}
			]
		}
	}
}

3.3、接下来换成nested的玩法

0.把这个索引删除再来一遍

DELETE financeblogs

1.创建如下索引。主要是mapping中的comments字段指定了类型为 nested。

PUT /financeblogs
{
  "mappings": {
    "blog": {
      "properties": {
        "title": {
          "type": "text"
        },
        "body": {
          "type": "text"
        },
        "tags": {
          "type": "keyword"
        },
        "published_on": {
          "type": "keyword"
        },
        "comments": {
          "type": "nested",
          "properties": {
            "name": {
              "type": "text"
            },
            "comment": {
              "type": "text"
            },
            "age": {
              "type": "short"
            },
            "rating": {
              "type": "short"
            },
            "commented_on": {
              "type": "text"
            }
          }
        }
      }
    }
  }
}

2.插入同样的目标数据

PUT /financeblogs/blog/docidart1
{
  "title": "Invest Money",
  "body": "Please start investing money as soon...",
  "tags": ["money", "invest"],
  "published_on": "18 Oct 2017",
  "comments": [
    {
      "name": "William",
      "age": 34,
      "rating": 8,
      "comment": "Nice article..",
      "commented_on": "30 Nov 2017"
    },
    {
      "name": "John",
      "age": 38,
      "rating": 9,
      "comment": "I started investing after reading this.",
      "commented_on": "25 Nov 2017"
    },
    {
      "name": "Smith",
      "age": 33,
      "rating": 7,
      "comment": "Very good post",
      "commented_on": "20 Nov 2017"
    }
  ]
}

3.使用nested查询方法

#查询name为John,age为34的记录发现是没有数据的。

GET /financeblogs/blog/_search?pretty
{
  "query": {
    "bool": {
      "must": [
        {
          "nested": {
            "path": "comments",
            "query": {
              "bool": {
                "must": [
                  {
                    "match": {
                      "comments.name": "John"
                    }
                  },
                  {
                    "match": {
                      "comments.age": 34
                    }
                  }
                ]
              }
            }
          }
        }
      ]
    }
  }
}

4.查询name为John,age为38的数据就是有的

4、父子和嵌套两种方式比对

嵌套(nested)父子文档
优点

读取性能高

(据官方:比父子快5~10倍)

父子文档可以独立更新
缺点更新子文档时需要更新整个文档

读取性能差,CPU占用率高

(需额外的内存去维护关系)

适应场景查询为主,子文档偶尔更新的场景

子文档频繁更新;

子文档经常查询。

嵌套文档看似只是文档内有一个集合字段,但内部存储完全不是。以下图嵌套文档为例;留言1,留言2,留言3在内部实际存储为4个独立文档。

同时,嵌套文档的字段类型需要设置为nested。设置成nested后就不能被直接查询了,需要使用nested查询。

总结来说:

1.普通子对象默认实现了一对多的关系,会损失子对象的边界,子对象属性的关联性也会丧失。

2.嵌套(nested)对象可以解决普通子对象存在的问题,但是它有两个缺点:一是更新文档的时候要全部更新,另外就是不支持子文档从属多个主文档的场景。

3.父子文档能解决前面两个存在的问题,但是它适用于写多读少的场景(查询效率较慢)。

关于nested更多其他语法,参见:

干货 | Elasticsearch Nested类型深入详解_es nest类型-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1181653.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于人工蜂鸟算法的无人机航迹规划-附代码

基于人工蜂鸟算法的无人机航迹规划 文章目录 基于人工蜂鸟算法的无人机航迹规划1.人工蜂鸟搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要:本文主要介绍利用人工蜂鸟算法来优化无人机航迹规划。 …

【kubernetes】k8s组件

文章目录 1、概述2、控制平面组件(Control Plane Components)2.1 kube-apiserver2.2 etcd2.3 kube-scheduler2.4 kube-controller-manager2.5 cloud-controller-manager 3、Node组件3.1 kubelet3.2 kube-proxy3.3 容器运行时(Container Runti…

基础算法-回溯算法-案例

现象: 基础算法-回溯算法-案例 基础算法-回溯算法从不同角度出发 去寻找答案 找到答案或者走不通了(根据需求:找一个答案还是列举全部答案) 则回溯返回继续从下一条路出发 去寻找答案, 一直到走完 常见案例: 案例一: 通过输入一个不重复数…

找到【SVM】中最优的惩罚项系数C

因为本来SVM是想找到间隔最大的分割面,所以C越大,SVC会选择边际更小的,能够更好的分类所有训练点的决策边界,不过模型的训练时间也会越长。如果C的设定值较小,那SVC会尽量最大化边界,决策功能会更简单&…

4.求1000以内的所有完数

#include<stdio.h> // 完数&#xff1a;一个数的所有的真因子 (即除了自身以外的约数)的和&#xff0c;恰好等于它自身 // 1 不是完数 // 4的因子&#xff1a;1 2 4 除了本身 4 不等于 1&#xff0b;2 所以4不是完数void fun(void){int sum,i,j;for(i2;i<1000;i)…

架构师必备-DDD之落地实践

1. 走进 DDD 1.1 为什么要用 DDD &#xff1f; 面向对象设计&#xff0c;数据行为绑定&#xff0c;告别贫血模型&#xff1b;降低复杂度&#xff0c;分而治之&#xff1b;优先考虑领域模型&#xff0c;而不是切割数据和行为&#xff1b;准确传达业务规则&#xff0c;业务优先…

Unity中Shader再议ATTENUATION

文章目录 前言一、实现实时阴影的投射1、直接复制之前实现投射阴影的Pass 二、实现实时阴影的接受&#xff0c;同时实现光照衰减1、在 v2f 中使用这个2、在 顶点着色器 中使用这个3、在 片元着色器 中使用这个 前言 在之前文章中&#xff0c;实现了 Global Illumination 的直接…

python 之切片

文章目录 基本切片语法负索引step 为负使用负数的 Step从右向左提取间隔提取 注意事项切片的应用切片运用到字符串、元组、range对象字符串切片基本字符串切片使用步长进行操作 元组切片基本元组切片使用步长进行操作 range 对象切片基本 range 切片使用步长进行操作 在 Python…

SPSS两变量相关性分析

1.两变量相关性分析 两变量相关性分析是统计学中用于评估两个变量之间是否存在线性关系以及关系紧密程度的一种方法。相关性的大小通常使用相关系数来衡量&#xff0c;最常用的是皮尔逊相关系数&#xff08;Pearson correlation coefficient&#xff09;&#xff0c;但还有斯皮…

简单讲讲RISC-V跳转指令基于具体场景的实现

背景 在 RISC-V指令集中&#xff0c;一共有 6 条有条件跳转指令&#xff0c;分别是 beq、bne、blt、bltu、bge、bgeu。如下是它们的定义与接口 BEQ rs1, rs2, imm ≠ BNE rs1, rs2, imm &#xff1c; BLT rs1, rs2, imm ≥ BGE rs1, rs2, imm < unsigned BLTU rs1…

Stable Diffusion源码调试(二)

Stable Diffusion源码调试&#xff08;二&#xff09; 个人模型主页&#xff1a;https://liblib.ai/userpage/369b11c9952245e28ea8d107ed9c2746/model Stable Diffusion版本&#xff1a;https://github.com/AUTOMATIC1111/stable-diffusion-webui/releases/tag/v1.4.1 分析S…

汽车标定技术(五)--基于模型开发如何生成完整的A2L文件(1)

1 数据对象的创建 CtrlH打开Model Explorer&#xff0c;在Base workspace中点击工具栏add&#xff0c;出现如下界面&#xff0c; 可以看到Simulink提供了多种数据类型 Matlab Variable&#xff1a;Simulink.Parameter&#xff1a;使用该数据对象表示工程应用中的标定量Simuli…

python爬虫怎么翻页 ?

首先&#xff0c;你需要安装相关的库。在你的命令行窗口中&#xff0c;输入以下命令来安装所需的库&#xff1a; pip install requests beautifulsoup4然后&#xff0c;你可以使用以下代码来爬取网页内容并翻页&#xff1a; package mainimport ("fmt""net/htt…

DAY 12 结构体 共用体 枚举02

1.结构体 结构体对齐(了解) 概述 typedef struct Data01 { char a; int b; }Data01; typedef struct Data02 { char a; char b; }Data02; void fun01(){ printf("%ld\n",sizeof(Data01)); printf("%ld\n",sizeof(Data02)); } 特点&#xff…

QuantLib学习笔记——一个简单的价值估算案例

⭐️ 前言 QuantLib很强大&#xff0c;它实现了很多金融工具及其价值估算方法&#xff0c;从最简单的折现模型&#xff0c;到利用BSM模型对期权进行定价&#xff0c;覆盖面相当齐全。本文以一个简单的净现值估算案例&#xff0c;开启笔者金融工具估值的旅程。 开上豪车&#…

〔003〕虚幻 UE5 基础教程和蓝图入门

✨ 目录 &#x1f388; 新建项目&#x1f388; 快捷操作&#x1f388; 镜头移动速度&#x1f388; 新建蓝图关卡&#x1f388; 打印字符串&#x1f388; 蓝图的快捷键&#x1f388; 场景中放置物体&#x1f388; 通过蓝图改变物体位置&#x1f388; 展现物体运动轨迹&#x1f3…

泛微移动管理平台E-mobile lang2sql接口任意文件上传漏洞

一、漏洞描述 泛微e-mobile,由高端OA泛微专业研发,是业内领先的移动OA系统,提供移动审批,移动考勤,移动报表,企业微信等丰富办公应用,支持多种平台运行,灵活易用安全性高。 e-mobile可满足企业日常管理中的绝大部分管理需求&#xff0c; 诸如市场销售、项目、采购、研发、客服…

了解高防服务器的工作原理

在当今互联网时代&#xff0c;网络安全问题日益突出&#xff0c;各种网络攻击层出不穷。为了保护企业的网络安全&#xff0c;高防服务器应运而生。那么&#xff0c;你是否了解高防服务器的工作原理呢?下面就让我们一起来探索一下。 高防服务器是一种能够有效抵御各种网络攻击的…

“小众”与“竞争”:打造爆款新能源车型的两大方法

引言&#xff1a;在动荡的新能源汽车市场中,品牌如何从众多竞争者中脱颖而出,捕捉消费者的心呢?是否是从广袤的"主流"市场着手,还是从具有潜力的”小众"市场切入?或者,是否需要重新定义与既定的竞争者进行正面对抗的方式? 在新能源汽车翻涌的市场潮流中&…