【ElasticSearch】ElasticSearch实战
初步检索
检索 ES 信息
1)、GET /_cat/nodes
:查看所有节点
127.0.0.1 44 83 1 0.01 0.01 0.00 dilm * 1b06a843b8e3
*代表主节点
2)、GET /_cat/health
:查看健康状况
1718265331 07:55:31 elasticsearch yellow 1 1 4 4 0 0 1 0 - 80.0%
green表示健康值正常
3)、GET /_cat/master
:查看主节点
7NZD92ZKTTGcvCiRiYgipw 127.0.0.1 127.0.0.1 1b06a843b8e3
4)、GET /_cat/indices
:查看所有索引 ,等价于mysql数据库的show databases;
green open .kibana_task_manager_1 sDt5UmEmSHqFXBxT7O80KQ 1 0 2 0 21.7kb 21.7kb green open .apm-agent-configuration iQ8r6SPhRkm2Cq86D2koWg 1 0 0 0 283b 283b yellow open index ilDKtPGtQDOSagS6tk9QPw 1 1 1 0 3.4kb 3.4kb green open .kibana_1 9vfcQSsNSWGunawX2uhkqQ 1 0 8 0 32.7kb 32.7kb
新增文档
保存一个数据,保存在哪个索引的哪个类型下(哪张数据库哪张表下),保存时用唯一标识指定
# 在customer索引下的external类型下保存1号数据 PUT customer/external/1 {"name":"John Doe" }
#! Deprecation: [types removal] Specifying types in document index requests is deprecated, use the typeless endpoints instead (/{index}/_doc/{id}, /{index}/_doc, or /{index}/_create/{id}). {"_index" : "customer", // 表明该数据在哪个数据库下"_type" : "external", // 表明该数据在哪个类型下"_id" : "1", // 表明被保存数据的id"_version" : 1, // 被保存数据的版本"result" : "created", // 表示创建了一条数据"_shards" : {"total" : 2,"successful" : 1,"failed" : 0},"_seq_no" : 0,"_primary_term" : 1 }
PUT 和 POST 的区别
-
POST如果不指定id,会自动生成id;指定id就会修改这个数据,并新增版本号
-
PUT必须指定id,一般用来做修改操作,不指定id会报错
查看文档
GET /customer/external/1
:查看customer索引下的external类型下的文档
{"_index" : "customer","_type" : "external","_id" : "1","_version" : 1,"_seq_no" : 0, // 并发控制字段,每次更新都会+1,用来做乐观锁"_primary_term" : 1, // 同上,主分片重新分配,如重启,就会变化"found" : true,"_source" : {"name" : "John Doe"} }
更新文档
POST customer/externel/1/_update {"doc":{"name":"John Smith"} } 或者 POST customer/externel/1 {"doc":{"name":"John Smith"} } 或者 PUT customer/externel/1 {"doc":{"name":"John Smith"} }
带有_update的情况下,POST操作会对比原文档数据,如果相同不做操作;PUT操作总会重新保存并增加version版本
删除文档或索引
ES并没有提供删除类型的操作,只提供了删除索引和文档的操作
DELETE customer/external/1 DELETE customer
{"_index": "customer","_type": "external","_id": "1","_version": 14,"result": "deleted","_shards": {"total": 2,"successful": 1,"failed": 0},"_seq_no": 22,"_primary_term": 6 }
批量操作_bulk
bulk api按顺序执行所有的action(动作)。如果一个单个的动作因任何原因失败,它将 继续处理 它后面剩余的动作。当bulk api返回时,它将提供每个动作的状态(与发送的顺序相同),所以您可以检查是否一个指定的动作是否失败了
# 对整个索引执行批量操作 POST /_bulk {"delete":{"_index":"website","_type":"blog","_id":"123"}} {"create":{"_index":"website","_type":"blog","_id":"123"}} {"title":"my first blog post"} {"index":{"_index":"website","_type":"blog"}} {"title":"my second blog post"} {"update":{"_index":"website","_type":"blog","_id":"123"}} {"doc":{"title":"my updated blog post"}}
{"took" : 227,"errors" : false,"items" : [{"delete" : {"_index" : "website","_type" : "blog","_id" : "123","_version" : 1,"result" : "not_found", // 1、没有该记录"_shards" : {"total" : 2,"successful" : 1,"failed" : 0},"_seq_no" : 0,"_primary_term" : 1,"status" : 404}},{"create" : {"_index" : "website","_type" : "blog","_id" : "123","_version" : 2,"result" : "created", // 2、创建成功"_shards" : {"total" : 2,"successful" : 1,"failed" : 0},"_seq_no" : 1,"_primary_term" : 1,"status" : 201}},{"index" : {"_index" : "website","_type" : "blog","_id" : "rDm8EJABRl6keg4IGZWd","_version" : 1,"result" : "created", // 3、保存成功"_shards" : {"total" : 2,"successful" : 1,"failed" : 0},"_seq_no" : 2,"_primary_term" : 1,"status" : 201}},{"update" : {"_index" : "website","_type" : "blog","_id" : "123","_version" : 3,"result" : "updated", // 4、更新成功"_shards" : {"total" : 2,"successful" : 1,"failed" : 0},"_seq_no" : 3,"_primary_term" : 1,"status" : 200}}] }
进阶检索
_search检索
_search检索支持两种方式:参数拼uri和参数放在请求体
# 请求参数方式检索 GET bank/_search?q=*&sort=account_number:asc 说明: q=* # 查询所有 sort # 排序字段 asc # 升序 # 请求参数放在请求体 GET /bank/_search {"query": { "match_all": {} },"sort": [{ "account_number": "asc" },{ "balance":"desc"}] }
返回内容:
-
took
– 花费多少ms搜索 -
timed_out
– 是否超时 -
_shards
– 多少分片被搜索了,以及多少成功/失败的搜索分片 -
max_score
–文档相关性最高得分 -
hits.total.value
- 多少匹配文档被找到 -
hits.sort
- 结果的排序key(列),没有的话按照score排序 -
hits._score
- 相关得分 (not applicable when usingmatch_all
)
DSL
ES提供了一个可以执行查询的Json风格的DSL(domain-specific language,领域特定语言),被称为Query DSL,该查询语言非常全面
如果针对于某个字段,那么它的结构如下: {QUERY_NAME: { # 使用的功能FIELD_NAME: { # 功能参数ARGUMENT: VALUE,ARGUMENT: VALUE,...} } }
示例 ,使用时不要加#注释内容
GET bank/_search {"query": { # 查询的字段"match_all": {}},"from": 0, # 从第几条文档开始查"size": 5,"_source":["balance"],"sort": [{"account_number": { # 返回结果按哪个列排序"order": "desc" # 降序}}] } _source为要返回的字段
query定义如何查询;
-
match_all查询类型【代表查询所有的索引】,es中可以在query中组合非常多的查询类型完成复杂查询;
-
from+size限定,完成分页功能;
-
sort排序,多字段排序,会在前序字段相等时后续字段内部排序,否则以前序为准;
Mapping映射
Mapping 是用来定义一个文档(document),以及它所包含的属性(field)是如何存储和索引的。使用maping来定义:
-
哪些字符串属性应该被看做全文本属性(full text fields);
-
哪些属性包含数字,日期或地理位置;
-
文档中的所有属性是否都嫩被索引(all 配置);
-
日期的格式;
-
自定义映射规则来执行动态添加属性;
-
查看mapping信息:GET bank/_mapping
创建索引并指定映射
第一次存储数据的时候es就猜出了映射 第一次存储数据前可以指定映射
PUT /my_index {"mappings": {"properties": {"age": {"type": "integer"},"email": {"type": "keyword" # 指定为keyword},"name": {"type": "text" # 全文检索。保存时候分词,检索时候进行分词匹配}}} }
查看映射
GET /my_index
{"my_index" : {"aliases" : { },"mappings" : {"properties" : {"age" : {"type" : "integer"},"email" : {"type" : "keyword"},"name" : {"type" : "text"}}},"settings" : {"index" : {"creation_date" : "1718270515822","number_of_shards" : "1","number_of_replicas" : "1","uuid" : "OfDvFnDvQiq8Jq-3oDHDog","version" : {"created" : "7040299"},"provided_name" : "my_index"}}} }
添加字段映射
PUT /my_index/_mapping {"properties": {"employee-id": {"type": "keyword","index": false # 字段不能被检索,只是一个冗余字段}} }
不能更新映射
对于已经存在的字段映射,我们不能更新。更新必须创建新的索引,进行数据迁移
数据迁移
先创建new_twitter的正确映射,然后使用如下方式进行数据迁移
6.0以后写法 POST reindex {"source":{"index":"twitter"},"dest":{"index":"new_twitters"} } 老版本写法 POST reindex {"source":{"index":"twitter","twitter":"twitter"},"dest":{"index":"new_twitters"} }
更多详情见: Reindex API | Elasticsearch Guide [7.6] | Elastic
分词
内置的分词只支持对英文的分词,安装 ik 分词器
SpringBoot 整合 ES
客户端选型
-
通过 9300 端口(ES 集群间通信也是 9300 端口), 维护一个 TCP 长连接
spring 提供了 spring-data-elasticsearch:transport-api.jar
-
springboot版本不同,transport-api.jar 不同,不能适配 ES 版本
-
7.x 已经不建议使用,8 以后就要废弃
-
-
通过 9200 端口,给 ES 发送 HTTP 请求
-
JestClient:非官方,更新慢
-
RestTemplate:ES 很多操作需要自己封装,麻烦
-
HttpClient:同上
-
Elasticsearch-Rest-Client:官方 RestClient,封装了 ES 操作,API 层次分明,上手简单
最终选择 Elasticsearch-Rest-Client(elasticsearch-rest-high-level-client),参考文档:Java High Level REST Client | Java REST Client [7.17] | Elastic
ES 做商品检索
商品上架需求
-
上架的商品才可以在网站展示
-
上架的商品可以被检索
商品如何检索
ES 比 MySQL 更适合做全文检索,它的数据存在内存中,对于电商中海量商品的搜索场景, 可以通过 ES 数据分片的集群部署方式,提供全文检索和复杂查询支持
对于搜索场景,我们要支持品牌、类型、属性规格的搜索
SKU 在 ES 中怎么存
分析:商品上架在 ES 中是存 SKU 还是 SPU?
-
检索的时候输入名字,是需要按照sku的title进行全文检索的
-
检素使用商品规格,规格是spu的公共属性,每个spu是一样的
-
按照分类id进去的都是直接列出spu的,还可以切换
-
我们如果将sku的全量信息保存到es中(包括spu属性〕就太多字段了
方案1
{skuId:1spuId:11skyTitile:华为xxprice:999saleCount:99attr:[{尺寸:5},{CPU:高通945},{分辨率:全高清}] } 在sku级别冗余存储规格属性 缺点:如果每个sku都存储规格参数(如尺寸),会有冗余存储,因为每个spu对应的sku的规格参数都一样 假设100万商品,每个spu平均规格属性有2kb数据,等于冗余存储多用了2个G的内存
方案2
sku索引 {spuId:1skuId:11 } attr索引 {spuId:11attr:[{尺寸:5},{CPU:高通945},{分辨率:全高清}] } 不冗余存储,规格属性只在spu级别保存了一份 缺点:因为展示的规格属性是动态计算出来的,如何计算?在我们搜索商品关键字时,ES 会搜索出所有标题里包含这个关键字的商品,聚合起来分析这些商品涉及的所有规格属性和属性值。如果在这种方案下实现动态计算,假设搜索“小米”有10w个商品,对应4000个spu,再根据4000个spu查询对应的规格属性 假设spuId用long类型,占8字节,一个请求占8B*4000=32000B=32KB 假设有1w人并发检索,就传了320MB的数据,占用大量网络带宽,很可能会网络阻塞
最终选择方案1,用空间换时间
建立索引
-
{ "type": "keyword" },保持数据精度问题,可以检索,但不分词
-
"analyzer": "ik_smart",中文分词器
-
"index": false,不可被检索,不生成index
-
"doc_values": false ,默认为true,不可被聚合,es就不会维护一些聚合的信息
PUT product {"mappings":{"properties": {"skuId":{ "type": "long" },"spuId":{ "type": "keyword" }, # 不可分词"skuTitle": {"type": "text","analyzer": "ik_smart" # 中文分词器},"skuPrice": { "type": "keyword" }, # 保证精度问题"skuImg" : { "type": "keyword" }, # 视频中有false"saleCount":{ "type":"long" },"hasStock": { "type": "boolean" }, # 只存是否有库存,不存库存量"hotScore": { "type": "long" }, # 热度评分"brandId": { "type": "long" },"catalogId": { "type": "long" },"brandName": {"type": "keyword"}, # 视频中有false"brandImg":{"type": "keyword","index": false, # 不可被检索,不生成index,只用做页面使用"doc_values": false # 不可被聚合,默认为true},"catalogName": {"type": "keyword" }, # 视频里有false"attrs": {"type": "nested", # 嵌入式对象,避免被扁平化处理"properties": {"attrId": {"type": "long" },"attrName": {"type": "keyword","index": false, # 不可被索引,不生成索引"doc_values": false},"attrValue": {"type": "keyword" }}}}} }
nested 嵌入式对象
数组类型的对象会被扁平化处理(对象的每个属性会分别存储到一起)
user.name=["aaa","bbb"] user.addr=["ccc","ddd"] 这种存储方式,可能会发生如下错误: 错误检索到{aaa,ddd},这个组合是不存在的
数组的扁平化处理会使检索能检索到本身不存在的,为了解决这个问题,就采用了嵌入式属性,数组里是对象时用嵌入式属性(不是对象无需用嵌入式属性)
nested阅读:ElasticSearch - 嵌套对象 nested_elasticsearch nested java-CSDN博客
使用聚合:Elastic search中使用nested类型的内嵌对象-CSDN博客
相关文章:
【ElasticSearch】ElasticSearch实战
初步检索 检索 ES 信息 1)、GET /_cat/nodes:查看所有节点 127.0.0.1 44 83 1 0.01 0.01 0.00 dilm * 1b06a843b8e3 *代表主节点 2)、GET /_cat/health:查看健康状况 1718265331 07:55:31 elasticsearch yellow 1 1 4 4 0 0…...
48-3 内网渗透 - 令牌操纵
访问令牌操纵 Windows 操作系统的访问控制模型是其安全性的重要组成部分,主要由访问令牌(Access Token)和安全描述符(Security Descriptor)构成。访问令牌是访问者持有的,而安全描述符则由被访问对象持有。通过对比访问令牌和安全描述符的内容,Windows 可以判断访问者是…...
架构师之 Kafka 核心概念入门
Kafka 核心概念 作为架构师,理解 Kafka 的核心概念至关重要。这些概念是构建高效、可靠的 Kafka 系统的基础。 以下是需要掌握的 Kafka 核心概念及其详细说明: 1. Topic 定义:Topic 是 Kafka 中用于存储和分类消息的逻辑命名空间。每个 Topic 代表一类数据流, 例如日志、…...

Redis通用命令详解
文章目录 一、Redis概述1.1 KEYS:查看符合模板的所有 key1.2 DEL:删除一个指定的 key1.3 EXISTS:判断 key 是否存在1.4 EXPIRE:给一个 key 设置有效期,有效期到期时该 key 会被自动删除1.5 TTL:查看一个 ke…...

物联网设备安装相关知识整理
拓扑图 对于ADAM-4150先接设备的整体的供电。 ADAM-4150就涉及到几个电子元器件的连接,一个是485-232的转换器,一个是将RS-232转换为USB的转接口,因为现在的计算机很多都去掉了RS-232接口而使用USB接口。 4150右侧有个拨码,分别两…...

React实现H5手势密码
监测应用进入前后台 在JavaScript中,监听H5页面是否在前台或后台运行,主要依赖于Page Visibility API。这个API在大多数现代浏览器中都是支持的,包括苹果的Safari和谷歌的Chrome(也就基本覆盖了Android和iOS平台)。下…...

[leetcode hot 150]第十五题,三数之和
题目: 给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k ,同时还满足 nums[i] nums[j] nums[k] 0 。请 你返回所有和为 0 且不重复的三元组。 注意:答案中不可以包含重复…...

视频AI分析定时任务思路解析
序言: 最近项目中用到视频ai分析,由于sdk涉及保密,不便透露,仅对定时任务分析的思路作出分享,仅供参考。 1、定时任务 由于ai服务器的性能上限,只能同时对64个rtsp流分析一种算法,或者对8个rts…...
tcp 粘包和拆包 及 解决粘包方案
什么是粘包和拆包 .TCP 是面向连接的,面向流的,提供高可靠性服务。收发两端(客户端和服务器端)都要有一一成对的 socket,因此,发送端为了将多个发给接收端的包,更有效的发给对方,使…...

【2024泰迪杯】B 题:基于多模态特征融合的图像文本检索20页论文及Python代码
【2024泰迪杯】B 题:基于多模态特征融合的图像文本检索20页论文及Python代码 相关链接 【2024泰迪杯】A 题:生产线的故障自动识别与人员配置 Python代码实现 【2024泰迪杯】B 题:基于多模态特征融合的图像文本检索Python代码实现 【2024泰迪…...

华为设备telnet 远程访问配置实验简述
一、实验需求: 1、AR1模拟电脑telnet 访问AR2路由器。 二、实验步骤: 1、AR1和AR2接口配置IP,实现链路通信。 2、AR2配置AAA模式 配置用户及密码 配置用户访问级别 配置用户telnet 访问服务 AR2配置远程服务数量 配置用户远程访问模式为AAA 配置允许登录…...
在HTML中,如何正确使用语义化标签?
在HTML中,使用语义化标签可以使得网页结构更加清晰和易于理解。以下是一些正确使用语义化标签的方法: 使用合适的标题标签(h1-h6)来标识网页的标题,以及页面中的各个区块的标题。 <h1>网页标题</h1> <…...
WHAT - 高性能和内存安全的 Rust(一)
目录 一、介绍1.1 示例代码1.2 关键特性内存安全零成本抽象:高效性能示例代码:使用迭代器的零成本抽象示例代码:泛型和单态化总结 并发编程:防止数据竞争Rust 并发编程示例Rust 的所有权系统防止数据竞争总结 丰富的类型系统包管理…...
八、C#运算符
C#运算符 晕杜甫是一种告诉编辑器执行特定的数学或逻辑操作的符号。C#有丰富的内置运算符,分类如下: 算术运算符关系运算符逻辑运算符位运算符赋值运算符其他运算符 算术运算符 下表显示了 C# 支持的所有算术运算符。假设变量 A 的值为 10,…...
【HiveSQL】join关联on和where的区别及效率对比
测试环境:hive on spark spark版本:3.3.1 一、执行时机二、对结果集的影响三、效率对比1.内连接1)on2)where 2.外连接1)on2)where 四、总结PS 一、执行时机 sql连接中,where属于过滤条件&#…...

如何解决windows自动更新,释放C盘更新内存
第一步:首先关闭windows自动更新组件 没有更新windows需求,为了防止windows自动更新,挤占C盘空间,所以我们要采取停止Windows Update服务。按下WinR打开运行对话框,输入services.msc, 然后按Enter。在服务…...

初学51单片机之PWM实例呼吸灯以及遇到的问题(已解答)
PWM全名Pulse Width Modulation中文称呼脉冲宽度调制 如图 这是一个周期10ms、频率是100HZ的波形,但是每个周期内,高低电平宽度各不相同,这就是PWM的本质。 占空比是指高电平占整个周期的比列,上图第一个波形的占空比是40%,第二个…...

手机天线都去哪里了?
在手机的演变历程中,天线的设计和位置一直是工程师们不断探索和创新的领域。你是否好奇,现在的手机为什么看不到那些曾经显眼的天线了呢? 让我们一起揭开这个谜题。 首先,让我们从基础开始:手机是如何发出电磁波的&…...

计算机网络 —— 应用层(电子邮件)
计算机网络 —— 应用层(电子邮件) 电子邮件发送电子邮件的过程SMTP特性工作流程 电子邮件格式MIME关键组件工作方式 POP/IMAPPOP(邮局协议)IMAP(因特网邮件访问协议) 基于万维网的电子邮箱特点优势常见的基…...
Java18新特性(极简)
一、引言 自1995年Java语言首次亮相以来,它已经成为企业级应用、移动应用和游戏开发等领域不可或缺的一部分。随着技术的不断进步,Java也在持续演化,每个新版本都带来了诸多新特性和性能优化,旨在提升开发者的编程效率和应用程序的…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...
synchronized 学习
学习源: https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖,也要考虑性能问题(场景) 2.常见面试问题: sync出…...

vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...

ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...
蓝桥杯 冶炼金属
原题目链接 🔧 冶炼金属转换率推测题解 📜 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V,是一个正整数,表示每 V V V 个普通金属 O O O 可以冶炼出 …...

C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...
QT3D学习笔记——圆台、圆锥
类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体(对象或容器)QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质(定义颜色、反光等)QFirstPersonC…...