当前位置: 首页 > 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;减少…...

Matlab | matlab常用命令总结

常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...

让AI看见世界:MCP协议与服务器的工作原理

让AI看见世界&#xff1a;MCP协议与服务器的工作原理 MCP&#xff08;Model Context Protocol&#xff09;是一种创新的通信协议&#xff0c;旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天&#xff0c;MCP正成为连接AI与现实世界的重要桥梁。…...

爬虫基础学习day2

# 爬虫设计领域 工商&#xff1a;企查查、天眼查短视频&#xff1a;抖音、快手、西瓜 ---> 飞瓜电商&#xff1a;京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空&#xff1a;抓取所有航空公司价格 ---> 去哪儿自媒体&#xff1a;采集自媒体数据进…...

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…...

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…...

Typeerror: cannot read properties of undefined (reading ‘XXX‘)

最近需要在离线机器上运行软件&#xff0c;所以得把软件用docker打包起来&#xff0c;大部分功能都没问题&#xff0c;出了一个奇怪的事情。同样的代码&#xff0c;在本机上用vscode可以运行起来&#xff0c;但是打包之后在docker里出现了问题。使用的是dialog组件&#xff0c;…...

多模态图像修复系统:基于深度学习的图片修复实现

多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...

4. TypeScript 类型推断与类型组合

一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式&#xff0c;自动确定它们的类型。 这一特性减少了显式类型注解的需要&#xff0c;在保持类型安全的同时简化了代码。通过分析上下文和初始值&#xff0c;TypeSc…...

逻辑回归暴力训练预测金融欺诈

简述 「使用逻辑回归暴力预测金融欺诈&#xff0c;并不断增加特征维度持续测试」的做法&#xff0c;体现了一种逐步建模与迭代验证的实验思路&#xff0c;在金融欺诈检测中非常有价值&#xff0c;本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...

通过MicroSip配置自己的freeswitch服务器进行调试记录

之前用docker安装的freeswitch的&#xff0c;启动是正常的&#xff0c; 但用下面的Microsip连接不上 主要原因有可能一下几个 1、通过下面命令可以看 [rootlocalhost default]# docker exec -it freeswitch fs_cli -x "sofia status profile internal"Name …...