当前位置: 首页 > news >正文

Elasticsearch中object类型与nested类型以及数组之间的区别

一、区别:

0、一般情况下用object 类型来查es中为json对象的字段数据,用nested来查es中为JsonArray数组类型的字段数据。
1、默认情况下ES会把JSON对象直接映射为object类型,只有手动设置才会映射为nested类型

2、object类型可以直接使用普通的逗号(.)查询,比如

{"query": {"term": {"inspector.id": {"value": "222"}}}
}

3、nested类型的查询需要使用nested查询:

{"query": {"nested": {"path": "inspector","query": {"term": {"inspector.id": {"value": "222"}}}}    }
}

4、两种查询方式不兼容,如果大家想做改动的话,需要对java程序进行修改,风险比较大。

5、存储方式不同。对象数组在后台是扁平化存储,嵌套对象数组是每个对象独立成文档存储。因此,对象数据有时会有"且"条件查询出"或"结果,嵌套对象的文档聚合可能会多计数(除非加reverse_nested),想保持数组中对象的独立性,就需要使用嵌套字段类型。

二、Object类型字段

1:mapping

注意,如果没有写明type,比如categoryObj,ES会默认object类型,并且就算查看mapping,也不会显示出来:

		// 所属类目,对象类型,注意这里没有写明type,ES则会默认为object"categoryObj": {//"type":"object","properties": {"class1": {"type": "keyword"},"class2": {"type": "keyword"},"class3": {"type": "keyword"}}}

2:增加数据

PUT test_index_20211220/e-com/1
{"id": "1","name": "L'oreal/欧莱雅复颜玻尿酸水光充盈导入膨润精华液","brand": "欧莱雅","price": 279,"desc": "补水 提拉紧致 淡化细纹","categoryObj": {"class1": "欧莱雅","class2": "补水","class3": "面部护理"}
}

3:查询

在样例数据中,“categoryObj"字段被默认设置为object类型(没有显示设置type),对于对象类型,在查询时需要用”."号连接整个字段:

GET test_index_20211220/_search
{"query": {"term": {"categoryObj.class1": "欧莱雅"}}
}

4:对象数组特性

我们知道了嵌套字段中的对象被ES存储为了独立的文档,那对象字段呢?ES在后台将对象字段进行打平处理,后台其实存储的是扁平结构,以categoryObj字段为例:

"categoryObj": [{"class1": "欧莱雅","class2": "补水","class3": "面部护理"},{"class1": "欧莱雅","class2": "补水","class3": "面部精华"},{"class1": "雅诗兰黛","class2": "美白","class3": "面霜"}
]

后台存储的其实是:

{"categoryObj.class1": ["欧莱雅","欧莱雅","雅诗兰黛"],"categoryObj.class2": ["补水","补水","美白"],"categoryObj.class3": ["面部护理","面部精华","面霜"]
}

这就牺牲了对象之间的独立性,有时候会带来一些影响,具体就是某些情况下,对对象数组的"且"查询可能会变成"或"查询。
这个时候我们去同时查询"欧莱雅"和"美白"这两个关键词,正常来说是不应该差出来任何文档的,因为categoryObj中没有任何一个对象同时具备"欧莱雅"和"美白"这两个关键词,可事实确不是这样:

GET test_index_20211220/_search
{"query": {"bool": {// filter上下文"filter": {"bool": {"must": [{"term": {"categoryObj.class1": "欧莱雅"}},{"term": {"categoryObj.class2": "美白"}}]}}}}
}

结果居然将文档查询出来了
所以当字段为数组的时候,建议使用nested类型字段。

三、Nested类型字段

1:mapping

 		// 所属类目,嵌套类型"categoryNst": {"type": "nested","properties": {"class1": {"type": "keyword"},"class2": {"type": "keyword"},"class3": {"type": "keyword"}}}

2:增加数据

PUT test_index_20211220/e-com/1
{"id": "1","name": "L'oreal/欧莱雅复颜玻尿酸水光充盈导入膨润精华液","brand": "欧莱雅","price": 279,"desc": "补水 提拉紧致 淡化细纹","categoryNst": {"class1": "欧莱雅","class2": "补水","class3": "面部护理"}
}

3:查询

GET test_index_20211220/_search
{"query": {"nested": {"path": "categoryNst",       #nested对象的查询深度"query": {"term": {// 在以前的版本中直接写 "class2": "补水"也是可以的,因为已经在外部声明了path// 不知道从哪个版本改了,现在必须写 "categoryNst.class2": "补水",否则报错"categoryNst.class2": "补水"}}}}
}

4: 嵌套字段的特性

嵌套字段其实是把其内部成员当做了一条独立文档进行了索引。如何理解这句话呢?在上面的数据中,"categoryNst"数组已经有两个对象成员了
ES在后台其实将这两个对象成员当成了两条独立文档进行索引,所以ES一共索引了3条文档(一条外部文档,两条嵌套字段对象的文档),这点可以从对嵌套字段的terms聚合中看出来:

GET test_index_20211220/_search
{"query": {"nested": {"path": "categoryNst","query": {"term": {"categoryNst.class2": "补水"}}}},"aggs": {"nestedAgg":{"nested": {"path": "categoryNst"},"aggs": {"termAgg": {"terms": {// 这里一样不能写成"class2",否则虽不报错,但聚合无结果。"field": "categoryNst.class2"}}}}}
}
{"took": 6,"timed_out": false,"_shards": {"total": 2,"successful": 2,"skipped": 0,"failed": 0},"hits": {"total": 1,"max_score": 0.18232156,"hits": []},"aggregations": {"nestedAgg": {"doc_count": 2,"termAgg": {"doc_count_error_upper_bound": 0,"sum_other_doc_count": 0,"buckets": [{"key": "补水","doc_count": 2}]}}}
}

明明只有一条整体的文档,但聚合结果却是2,岂不是结果错误了?如何才能得到我们需要的结果呢?这个时候就要用到反转嵌套(reverse_nested),改写上面查询语句的聚合部分:

GET test_index_20211220/_search
{"size":0,"query": {"nested": {"path": "categoryNst","query": {"term": {"categoryNst.class2": "补水"}}}},"aggs": {"nestedAgg":{"nested": {"path": "categoryNst"},"aggs": {"termAgg": {"terms": {"field": "categoryNst.class2"},"aggs": {"reverseAgg": {"reverse_nested": {}}}}}}}
}

5:java查询

 public static void main(String[] args) {//创建ES客户端RestHighLevelClient esClient = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));//创建搜索对象SearchRequest searchRequest = new SearchRequest();searchRequest.indices("user");//构建请求体SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//查询数据-对nested类型数据查询searchSourceBuilder.query(QueryBuilders.nestedQuery("check_error", QueryBuilders.termsQuery("check_error.errtype", errtype), ScoreMode.None));//发送请求searchRequest.source(searchSourceBuilder);SearchResponse search = null;try {search = esClient.search(searchRequest, RequestOptions.DEFAULT);} catch (IOException e) {throw new RuntimeException(e);}//解析结果SearchHits hits = search.getHits();for (SearchHit hit : hits) {System.out.println(hit.getSourceAsString());}//关闭ES客户端esClient.close();}

四、数组类型字段

1:mapping

ES中没有专门的数组类型,默认情况下任何字段都可以包含一个或者多个值,但一个数组中的值必须是同一种类型。

 		// 数组类型"comments": {"type": "keyword"}

2:增加数据

当数组类型字段(comments)中只有一个数据时:

GET test_index_20211220/e-com/1
{"_index": "test_index_20211220","_type": "e-com","_id": "1","_version": 1,"found": true,"_source": {"id": "1","name": "L'oreal/欧莱雅复颜玻尿酸水光充盈导入膨润精华液","brand": "欧莱雅","price": 279,"desc": "补水 提拉紧致 淡化细纹","comments": "还没有用,赠品跟欧莱雅旗舰店的同款赠品有差异。味道也不一样"}
}

可以看到此时的comments还不是数组,现在我们增加一条评论,覆盖写入一次:

PUT test_index_20211220/e-com/1
{"id": "1","name": "L'oreal/欧莱雅复颜玻尿酸水光充盈导入膨润精华液","brand": "欧莱雅","price": 279,"desc": "补水 提拉紧致 淡化细纹","comments": ["还没有用,赠品跟欧莱雅旗舰店的同款赠品有差异。味道也不一样","只有这支玻璃尿酸水光充盈是真的"]
}

重新查询,可以看到,"commts"在索引的时候,如果有多个值,则会自动转化成了数组,且文档版本号+1:

GET test_index_20211220/e-com/1 
{"_index": "test_index_20211220","_type": "e-com","_id": "1","_version": 2,"found": true,"_source": {"id": "1","name": "L'oreal/欧莱雅复颜玻尿酸水光充盈导入膨润精华液","brand": "欧莱雅","price": 279,"desc": "补水 提拉紧致 淡化细纹","comments": ["还没有用,赠品跟欧莱雅旗舰店的同款赠品有差异。味道也不一样","只有这支玻璃尿酸水光充盈是真的"]}
}

3:查询

此时数组类型就当做正常的字段进行查询即可

GET my_test_index/_search
{"query": {"bool": {"must": [{"terms": {"label": ["10","100"]}},{"term": {"name": {"value": "旺仔33333"}}}]}}
}

相关文章:

Elasticsearch中object类型与nested类型以及数组之间的区别

一、区别: 0、一般情况下用object 类型来查es中为json对象的字段数据,用nested来查es中为JsonArray数组类型的字段数据。 1、默认情况下ES会把JSON对象直接映射为object类型,只有手动设置才会映射为nested类型 2、object类型可以直接使用普…...

办公文档,私人专用

一、安装Minio 1.1、创建文件夹,并在指定文件夹中下载minio文件 cd /opt mkdir minio cd minio touch minio.log wget https://dl.minio.io/server/minio/release/linux-amd64/minio1.2、赋予minio文件执行权限 chmod 777 minio1.3、启动minio ./minio server /…...

linux 使用log4cpp记录项目日志

为什么要用log4cpp记录项目日志 在通常情况下,Linux/UNIX 每个程序在开始运行的时刻,都会打开 3 个已经打开的 stream. 分别用来输入,输出,打印错误信息。通常他们会被连接到用户终端。这 3 个句柄的类型为指向 FILE 的指针。可以…...

Kafka集群部署

文章目录 一、实例配置二 、zookeeper集群安装三、kafka集群安装四、验证 没有提示,所有机器都执行 在kafka集群中引入zookeeper,主要是为了管理kafka集群的broker。负责管理集群的元数据信息,确保 Kafka 集群的高可用性、高性能和高可靠性。…...

软件测试|深入理解SQL CROSS JOIN:交叉连接

简介 在SQL查询中,CROSS JOIN是一种用于从两个或多个表中获取所有可能组合的连接方式。它不依赖于任何关联条件,而是返回两个表中的每一行与另一个表中的每一行的所有组合。CROSS JOIN可以用于生成笛卡尔积,它在某些情况下非常有用&#xff…...

数据权限-模型简要分析

权限管控可以通俗的理解为权力限制,即不同的人由于拥有不同权力,他所看到的、能使用的可能不一样。对应到一个应用系统,其实就是一个用户可能拥有不同的数据权限(看到的)和操作权限(使用的)。 …...

echarts柱状图加单位,底部文本溢出展示

刚开始设置了半天都不展示单位,后来发现是被挡住了,需要调高top值 // 基于准备好的dom,初始化echarts实例var myChart echarts.init(document.getElementById("echartD"));rankOption {// backgroundColor: #00265f,tooltip: {…...

x-cmd pkg | gh - GitHub 官方 CLI

目录 简介首次用户功能特点与 x-cmd gh 模块的关系相关作品进一步探索 简介 gh,是由 GitHub 官方使用 Go 语言开发和维护的命令行工具,旨在脚本或是命令行中便捷管理和操作 GitHub 的工作流程。 注意: 由于 x-cmd 提供了同名模块,因此使用官…...

Python解析XML,简化复杂数据操作的最佳工具!

更多Python学习内容:ipengtao.com XML(可扩展标记语言)是一种常见的文本文件格式,用于存储和交换数据。Python提供了多种库和模块,用于解析和操作XML文件。本文将深入探讨如何使用Python操作XML文件,包括XM…...

rpm数据库被破坏,无法使用yum

转载说明:如果您喜欢这篇文章并打算转载它,请私信作者取得授权。感谢您喜爱本文,请文明转载,谢谢。 问题描述: 云服务器在安装了开源的HIDS插件后,发现安装了插件的服务器全部突然无法正常使用yum安装软件…...

国标GB28181视频监控EasyCVR平台:视频集中录制存储/云端录像功能及操作介绍

安防视频监控系统EasyCVR视频综合管理平台,采用了开放式的网络结构,可以提供实时远程视频监控、视频录像、录像回放与存储、告警、语音对讲、云台控制、平台级联、磁盘阵列存储、视频集中存储、云存储等丰富的视频能力,同时还具备权限管理、设…...

Wargames与bash知识11

Wargames与bash知识11 bandit19 关卡提示: 要获得对下一级别的访问权限,您应该使用家目录中的setuid二进制文件。在不带参数的情况下执行它,以了解如何使用。在使用setuid二进制文件后,可以在通常的位置(/etc/bandit…...

Python 基础(一):基本语句

目录 1 条件语句2 循环语句2.1 for 循环2.2 while 循环2.3 break2.4 continue 3 pass 语句 1 条件语句 在进行逻辑判断时,我们需要用到条件语句,Python 提供了 if、elif、else 来进行逻辑判断。格式如下所示: if 判断条件1:执行语句1... el…...

Hibernate实战之操作MySQL数据库(2024-1-8)

Hibernate实战之操作MySQL数据库 2024.1.8 前提环境(JavaMySQLNavicatVS Code)1、Hibernate简介1.1 了解HQL 2、MySQL数据库建表2.1 编写SQL脚本2.2 MySQL执行脚本 3、Java操作MySQL实例(Hibernate)3.1 准备依赖的第三方jar包3.2 …...

【Spring Boot 3】【数据源】自定义JDBC多数据源

【Spring Boot 3】【数据源】自定义JDBC多数据源 背景介绍开发环境开发步骤及源码工程目录结构总结背景 软件开发是一门实践性科学,对大多数人来说,学习一种新技术不是一开始就去深究其原理,而是先从做出一个可工作的DEMO入手。但在我个人学习和工作经历中,每次学习新技术…...

番茄工作法

番茄工作法是一种时间管理方法,主要适用于专注工作。它的基本步骤包括: 设定一个25分钟的闹钟。默念三二一(321法则),开始全身心投入工作。用专注的状态高效工作25分钟,不允许走神。如果做到了步骤3&#…...

【uniapp】调用阿里云OCR图片识别文字:

文章目录 一、效果&#xff1a;二、实现&#xff1a; 一、效果&#xff1a; 二、实现&#xff1a; 【阿里官方】高精版OCR文字识别【最新版】-云市场-阿里云 <template><view class"container"><!-- 选择图片 --><button click"imageO…...

软考高级选择考哪个好?

&#x1f4d2;软考高级总共5个科目&#xff0c;同样是高级证书&#xff0c;认可度也有区别! 大家一般在「信息系统项目管理师」✔️和「系统架构设计师」✔️二选一 1️⃣信息系统项目管理师 ❤️信息系统项目管理师也叫「高项」&#xff0c;考试内容主要是「项目管理」相关&am…...

在云服务器ECS上用Python写一个搜索引擎

在云服务器ECS上用Python写一个搜索引擎 一、场景介绍二、搜索引擎的组成2.1 网页的爬取及排序2.2 用户使用搜索引擎进行搜索 三、操作步骤3.1 环境准备3.2 安装Anaconda3.3 安装Streamlit3.4 下载搜索引擎代码3.5 运行搜索引擎 四、常见问题4.1 运行setup.py时可能的问题4.2 如…...

Python在智能手机芯片研发

Python在智能手机芯片研发中扮演着重要的角色。以下是几个方面的重要性&#xff1a; 快速原型设计&#xff1a;Python具有简洁易读的语法和丰富的第三方库&#xff0c;使工程师能够快速构建原型和进行快速迭代。这对于芯片研发来说&#xff0c;可以加快开发速度&#xff0c;减少…...

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包

文章目录 现象&#xff1a;mysql已经安装&#xff0c;但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时&#xff0c;可能是因为以下几个原因&#xff1a;1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

JS手写代码篇----使用Promise封装AJAX请求

15、使用Promise封装AJAX请求 promise就有reject和resolve了&#xff0c;就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...

JavaScript 数据类型详解

JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型&#xff08;Primitive&#xff09; 和 对象类型&#xff08;Object&#xff09; 两大类&#xff0c;共 8 种&#xff08;ES11&#xff09;&#xff1a; 一、原始类型&#xff08;7种&#xff09; 1. undefined 定…...

Caliper 负载(Workload)详细解析

Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...

Qt 事件处理中 return 的深入解析

Qt 事件处理中 return 的深入解析 在 Qt 事件处理中&#xff0c;return 语句的使用是另一个关键概念&#xff0c;它与 event->accept()/event->ignore() 密切相关但作用不同。让我们详细分析一下它们之间的关系和工作原理。 核心区别&#xff1a;不同层级的事件处理 方…...

在树莓派上添加音频输入设备的几种方法

在树莓派上添加音频输入设备可以通过以下步骤完成&#xff0c;具体方法取决于设备类型&#xff08;如USB麦克风、3.5mm接口麦克风或HDMI音频输入&#xff09;。以下是详细指南&#xff1a; 1. 连接音频输入设备 USB麦克风/声卡&#xff1a;直接插入树莓派的USB接口。3.5mm麦克…...

nnUNet V2修改网络——暴力替换网络为UNet++

更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...

大数据治理的常见方式

大数据治理的常见方式 大数据治理是确保数据质量、安全性和可用性的系统性方法&#xff0c;以下是几种常见的治理方式&#xff1a; 1. 数据质量管理 核心方法&#xff1a; 数据校验&#xff1a;建立数据校验规则&#xff08;格式、范围、一致性等&#xff09;数据清洗&…...