ElasticSearch介绍+使用
ElasticSearch
1.背景
ElasticSearch的最明显的优势在于其分布式特性,能够扩展到上百台服务器,极大地提高了服务器的容错率。在大数据时代背景下,ElasticSearch与传统的数据库相比较,能够应对大规模的并发搜索请求,同时提供了包括布尔查询、短语查询、模糊匹配、排序等强大便捷的功能。
ElasticSearch是基于lucene实现的,而lucene是一个只限于Java语言的搜索引擎类库,属于Apache公司的1999年开发的项目。而ElasticSearch在lucene的基础上支持分布式,并且提供了Restful接口,减少了整合进项目的复杂度,同时也支持任何语言调用,使得其成为最流行的搜索引擎类库。
总结下来,ElasticSearch就是一个开源的分布式搜索引擎,可以用来实现搜索、日志统计、分析、系统监控等功能,同时具有很好地扩展性,且通过RestFulAPI简化了其使用。
相较于MySQL来说,ElasticSearch擅长海量数据的搜索、分析、计算,但在事务操作的安全和一致方面来说不如MySQL,在使用时往往采取二者结合使用,如对安全性要求较高的操作使用MySQL,而对于查询性能要求较高的操作采用ElasticSearch。
2.倒排索引
ElasticSearch之所以能够高效率地实现模糊查询、词组查询等功能,是由于其采用了一种倒排索引的模式。所谓倒排索引其实是相较于MySQL中的正向索引而言的。
select * from student where name like %张三%;
对于以上的SQL来说,由于采用了%前缀模糊查询,因此必定会导致全表扫描,在数据量大的情况下效率会非常低下。为了解决这种问题,ElasticSearch采用的是倒排索引。
了解倒排索引前,需要知道在ElasticSearch中有几个关键的概念,类比于数据库而言,ElasticSearch中有索引(indices)、类型(types)、文档(documents)、字段(fields),对应于数据库中的数据库(database)、表(tables)、行(rows)、列(columns)。其实在ElasticSearch中,面向的是Json文档,其字段就是Json中的键,而文档内容就是其值,另外,在ElasticSearch中的请求语句是Json风格的,被称为DSL。
例如:
{"id":"1","姓名":"张大三","专业":"计算机软件工程","绩点":"4.0"
},
{"id":"2","姓名":"李小四","专业":"电子与计算机工程","绩点":"3.5"
},
{"id":"3","姓名":"王小五","学号":"电子与自动化控制","绩点":"3.0"
}
姓名 | 专业 | 绩点 | |
---|---|---|---|
1 | 张大三 | 计算机软件工程 | 4.0 |
2 | 李小四 | 电子与计算机工程 | 3.5 |
3 | 王小五 | 电子与自动化控制 | 3.0 |
不同类型的文档可以组织在一起成为一个索引,如商品索引、学生索引、用户索引等。
倒排索引会对每一个文档的数据利用算法进行分词,得到一个个词条,然后根据词条以及其位置信息创建一个索引。
词条 | 文档id |
---|---|
计算机 | 1,2 |
软件 | 1 |
工程 | 1,2 |
电子 | 2,3 |
自动化控制 | 3 |
这样当用户输入如“计算机软件”进行搜索的时候就可以根据分词查找计算机和软件,去词条列表中查询到文档id,再根据文档id去原索引中查询得到1,2两条数据。这种根据词条找文档的过程就体现了倒排索引的特点。
注意:由倒排索引的原理不难看出,倒排索引提高模糊查询的办法是预先对已有的数据进行了分词处理,然后形成了一个词条的索引,相当于将原本查询所需的时间提前到了增加数据时处理的时候,因此倒排索引不适合高频动态数据,且对于数值型或者范围查询而言更擅长处理文本查询。
3.ELK
ELK是ElasticSearch技术栈的三大开源框架的首字母大写简称,分别是ElasticSearch、Logstash、Kibana,三者也被并称为ElasticStack。
Logstash是中央数据流引擎,主要功能是从各种数据源中收集、转换并将数据传送到目标存储中,比如 Elasticsearch 或者文件系统 。其典型使用场景有日志管理、事件数据处理、数据ETL。
Kibana 是一个开源的数据可视化与探索工具,专为与 Elasticsearch 配合使用而设计。它提供了强大的图形界面,用户可以通过 Kibana 从 Elasticsearch 中查询、分析和可视化数据。Kibana 是 Elastic Stack (ELK Stack) 的重要组成部分,主要用于展示和监控存储在 Elasticsearch 中的数据。
ELK的代表性作用就是日志分析和收集,除此之外也支持数据分析等功能。
4.Mapping
在ES中,Mapping(映射)定义了字段的结构和类型,决定了ES如何存储和索引文档中的数据。
Mapping常见的映射属性有:
1.type
定义字段的类型。常见类型有字符串、数字、布尔值、日期等。
2.index
定义字段是否需要被索引。index:true表示字段可以被搜索,index:false表示该字段不会被索引,不能用于搜索。
3.format
对于日期字段,format属性定义了日期的格式,例如format:"yyyy-MM-dd HH:mm:ss"。
4.analyzer
用于文本字段,定义文本分词器。例如,可以使用标准分词器、简单分词器或者自定义分词器。
5.field name
定义字段的名称。通常ES会更具文档中的字段名称自动生成映射,也可以自定义字段名。
6.muti-fields
定义一个字段可以以多种方式索引。例如,一个文本字段可以既用于全文搜索(分词),又用于精准匹配(不分词)。
Mapping常见的数据类型(type)有:
1.文本类型
text:用于存储需要全文搜索的文本。会进行分词。
keyword:用于存储不分词的精确值,比如标签、状态、URL等。
2.数字类型
integer:整数类型
long:长整型数值
float:单精度浮点数
double:双精度浮点数
3.日期类型
date:存储日期和时间数据,支持多种格式。
4.布尔类型
boolean:true或false。
5.二进制类型
binary:存储二进制数据,通常用于需要存储原始数据但是不用于搜索的情况。
6.对象类型
object:用于嵌套的JSON对象,允许在文档内存储复杂的嵌套结构。
7.数组类型
array:在ElasticSearch中,任何字段都可以是数组,数组的每个元素都具有相同的数据类型。
例如:
{"mappings": {"properties": {"name": {"type": "text","analyzer": "standard"},"age": {"type": "integer"},"birthdate": {"type": "date","format": "yyyy-MM-dd"},"is_active": {"type": "boolean"}}}
}
5.索引库的CRUD
创建索引及映射
PUT /{my_index}
{"settings":{"number_of_shards":3,"number_of_replicas":2},"mappings":{"properties":{"name":{"type":"text"},"age":{"type":"integer"},"email":{"type":"keyword"}}}
}
这里的settings是配置索引的分片数和副本数。比如这里设置了3个主分片和2个副本分片。
查询
GET /{my_index}
修改
索引库一旦创建,就无法修改mapping,因为数据结构改变就需要重新创建倒排索引,耗费巨大。但是可以添加新的字段到mapping中。
PUT /{my_index}/_mapping
{"properties":{"new_field":{"type":"integer"}}
}
删除
DELETE /{my_index}
6.文档的CRUD
新增文档
#POST /{my_index}/_doc/{id}
POST /student/_doc/1
查询文档
#GET /{my_index}/_doc/{id}
GET /student/_doc/1
删除文档
#DELETE /{my_index}/_doc/{id}
DELETE /my_index/_doc/1
修改文档
#全量修改:覆盖原来的文档
PUT /{my_index}/_doc/{id}
{"field1":"value1","field2":"value2",// ...
}#增量修改:只修改指定id匹配的文档中的部分字段
POST /{my_index}/_update/{id}
{"doc":{"field":"new_value"}
}
7.在Java中封装使用
使用ElasticSearch客户端(Java为例)
依赖:
<dependencies><!-- Elasticsearch Client --><dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId><version>7.10.2</version></dependency><!-- Jackson for JSON Parsing --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.12.3</version></dependency><!-- Apache HttpComponents for Elasticsearch --><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.13</version></dependency>
</dependencies>
封装思路:使用Java操作ES时需要创建ES客户端和索引请求,如果每次执行CRUD操作时都要创建那么会导致代码冗余,且频繁创建和关闭客户端连接会降低性能。所以通常的做法是将客户端的初始化和管理独立出来以确保高效、复用和易维护。这里采用单例模式将客户端封装为一个单例类,确保在整个声明周期中复用同一个客户端实例。
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.RestClient;
import org.apache.http.HttpHost;public class ElasticsearchClientSingleton {private static RestHighLevelClient client = null;private ElasticsearchClientSingleton() { }public static RestHighLevelClient getClient() {if (client == null) {synchronized (ElasticsearchClientSingleton.class) {if (client == null) {client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));}}}return client;}public static void closeClient() throws IOException {if (client != null) {client.close();}}
}
然后将索引创建放在应用启动时执行一次,避免每次CRUD操作都重复创建索引:
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.settings.Settings;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;public class ElasticsearchIndexManager {public static void createIndexIfNotExists(String indexName) throws IOException {RestHighLevelClient client = ElasticsearchClientSingleton.getClient();// 检查索引是否存在GetIndexRequest getIndexRequest = new GetIndexRequest(indexName);boolean exists = client.indices().exists(getIndexRequest, RequestOptions.DEFAULT);if (!exists) {// 如果索引不存在,则创建索引CreateIndexRequest createIndexRequest = new CreateIndexRequest(indexName);createIndexRequest.settings(Settings.builder().put("index.number_of_shards", 3).put("index.number_of_replicas", 2));// 使用 Jackson 构建 mappingObjectMapper mapper = new ObjectMapper();ObjectNode mapping = mapper.createObjectNode();ObjectNode properties = mapping.putObject("properties");properties.putObject("name").put("type", "text");properties.putObject("age").put("type", "integer");properties.putObject("email").put("type", "keyword");createIndexRequest.mapping(mapping.toString(), XContentType.JSON);client.indices().create(createIndexRequest, RequestOptions.DEFAULT);System.out.println("索引创建成功!");} else {System.out.println("索引已存在!");}}
}
由于将CRUD操作与索引和客户端管理分离,只需要专注于数据的操作,客户端和索引的创建在应用启动时已经完成:
public class ElasticsearchCrudOperations {// 创建文档public static void createDocument(String indexName, String documentId, String jsonString) throws IOException {RestHighLevelClient client = ElasticsearchClientSingleton.getClient();// 确保索引存在ElasticsearchIndexManager.createIndexIfNotExists(indexName);IndexRequest indexRequest = new IndexRequest(indexName).id(documentId).source(jsonString, XContentType.JSON);client.index(indexRequest, RequestOptions.DEFAULT);System.out.println("文档创建成功!");}// 读取文档public static void getDocument(String indexName, String documentId) throws IOException {RestHighLevelClient client = ElasticsearchClientSingleton.getClient();// 确保索引存在ElasticsearchIndexManager.createIndexIfNotExists(indexName);GetRequest getRequest = new GetRequest(indexName, documentId);GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);if (getResponse.isExists()) {String sourceAsString = getResponse.getSourceAsString();System.out.println("文档内容: " + sourceAsString);} else {System.out.println("文档不存在!");}}// 更新文档public static void updateDocument(String indexName, String documentId, String jsonString) throws IOException {RestHighLevelClient client = ElasticsearchClientSingleton.getClient();// 确保索引存在ElasticsearchIndexManager.createIndexIfNotExists(indexName);UpdateRequest updateRequest = new UpdateRequest(indexName, documentId).doc(jsonString, XContentType.JSON);client.update(updateRequest, RequestOptions.DEFAULT);System.out.println("文档更新成功!");}// 删除文档public static void deleteDocument(String indexName, String documentId) throws IOException {RestHighLevelClient client = ElasticsearchClientSingleton.getClient();// 确保索引存在ElasticsearchIndexManager.createIndexIfNotExists(indexName);DeleteRequest deleteRequest = new DeleteRequest(indexName, documentId);client.delete(deleteRequest, RequestOptions.DEFAULT);System.out.println("文档删除成功!");}
}
相关文章:
ElasticSearch介绍+使用
ElasticSearch 1.背景 ElasticSearch的最明显的优势在于其分布式特性,能够扩展到上百台服务器,极大地提高了服务器的容错率。在大数据时代背景下,ElasticSearch与传统的数据库相比较,能够应对大规模的并发搜索请求,同…...

Redis——常用数据类型List
目录 List列表常用命令lpushlpushxrpushrpushlrangelpoprpoplindexlinsertllenlremltrim key start stoplset 阻塞版本命令blpopbrpop list的编码方式list的应用 List列表 Redis中的list相当于数组,或者 顺序表,一些常用的操作可以通过下面这张图来理解…...

前端基础知识+算法(一)
文章目录 算法二分查找条件注意方式基本原理左闭右闭正向写法 左闭右开正向写法 前端基础知识定时器及清除盒子垂直水平居中的方式垂直水平1.flex布局2.grid布局3.定位对于块级元素 解决高度塌陷的方式1.给父元素一个固定的高度2.给父元素添加属性 overflow: hidden;3.在子元素…...

photozoom classic 9解锁码2024年最新25位解锁码
photozoom classic 9 破解版顾及比恐龙还要稀有,我曾经和你一样一直再找,找了好几个月,也没有找到真的破解版,下载很多次, 都是病毒插件之类的 我昨天下了几次,没有一个不附带插件病毒木马的.......&#x…...

Oracle发邮件功能:设置的步骤与注意事项?
Oracle发邮件配置教程?如何实现Oracle发邮件功能? Oracle数据库作为企业级应用的核心,提供了内置的发邮件功能,使得数据库管理员和开发人员能够通过数据库直接发送邮件。AokSend将详细介绍如何设置Oracle发邮件功能。 Oracle发邮…...
优化理论及应用精解【9】
文章目录 二次型函数二次型函数详细解释一、定义二、性质三、应用四、示例五、图表辅助说明(由于文本限制,无法直接提供图表) “西尔维斯特准则”一、定义二、来源三、应用场景 参考文献 二次型函数 二次型函数详细解释 一、定义 二次型函…...

nginx实现https安全访问的详细配置过程
文章目录 前言什么是 HTTP?什么是 HTTPS?HTTP 和 HTTPS 的区别为什么 HTTPS 被称为安全的?配置过程配置自签名证书 前言 首先我们来简单了解一下什么是http和https以及他们的区别所在. 什么是 HTTP? HTTP,全称为“超…...
1. TypeScript基本语法
TypeScript 学习总结 TypeScript 是一种 JavaScript 的超集,增加了静态类型检查和编译时错误检测,从而提高了代码的可维护性和可靠性。以下是 TypeScript 的基础知识总结,包括语法、运算符、数据类型、变量声明和作用域。 ## 基本语法TypeS…...
C# UDP与TCP点发【速发速断】模式
1、UDP 客户端 //由于收发都在本机,所以只用一个IP地址 IPAddress addr IPAddress.Parse("127.0.0.1"); var ptLocal new IPEndPoint(addr,9001);//本机节点,用于发送var ptDst new IPEndPoint(addr,9002);//目标节点…...

pikachu下
CSRF(跨站请求伪造) CSRF(get) url变成了这样了,我们就可以新开个页面直接拿url去修改密码 http://pikachu-master/vul/csrf/csrfget/csrf_get_login.php?username1&password2&submitLogin CSRF(post) 这里只是请求的方式不同,…...

Go语言开发im-websocket服务和vue3+ts开发类似微信pc即时通讯
前言 IM即时通讯聊天, 为软件开发者打造,不依赖第三方sdk,完全用Go语言开发即时通讯服务,支持H5、Electron、Wails 、Uniapp和各种小程序的IM即时通讯, 快速实现私聊、群聊、在线客服!让你快速搭建一个微信聊天系统,打…...

Redis如何实现分布式锁
目录 获取锁: 释放锁: Lua脚本: Redisson 分布式锁是,满足分布式系统或集群模式下多进程可见并且互斥的锁,因为我们熟知的java中的锁只是在单体架构下单个jvm中才会生效,如果部署了多个jvm则会导致新的…...

面向对象程序设计之继承(C++)
1.继承的定义 1.1继承的概念 继承(inheritance)机制是⾯向对象程序设计使代码可以复⽤的最重要的⼿段,它允许我们在保持原有类特性的基础上进⾏扩展,增加⽅法(成员函数)和属性(成员变量),这样产⽣新的类,称派⽣类。继承 呈现了⾯向…...

IAPP发布《2024年人工智能治理实践报告》
文章目录 前言一、黑箱问题►透明度、可理解性与可解释性二、法律和政策中的注意事项►欧盟的《通用数据保护条例》►欧盟的AI法案►NIST的AI风险管理框架►美国的第14110号行政命令►《生成式人工智能服务管理暂行办法》►新加坡的AI验证三、实施人工智能治理►模型卡与系统卡…...

了解MySQL 高可用架构:主从备份
为了防止数据库的突然挂机,我们需要对数据库进行高可用架构。主从备份是常见的场景,通常情况下都是“一主一从/(多从)”。正常情况下,都是主机进行工作,从机进行备份主机数据,如果主机某天突然意外宕机,从机…...

[OpenCV] 数字图像处理 C++ 学习——15像素重映射(cv::remap) 附完整代码
文章目录 前言1.像素重映射理论基础2.代码实现(1) remap()细节(2)水平翻转(2)垂直翻转(3)旋转 180 度(4)径向扭曲 3.完整代码 前言 像素重映射将图像中的每个像素映射到新位置,实现图像的扭曲、校正等操作。在 OpenCV 中,cv::remap() 函数就是用于实现这…...
Oreace每日运维操作
一.Oreace每日运维操作 目录 一.Oreace每日运维操作 1.1、确认所有的INSTANCE状态正常 1.2、检查文件系统的使用(剩余空间) 1.3 lwh暗码,,、检查日志文件和trace文件记录 1.4 lwh、检查数据库当日备份…...

【XR】AR HUD
1. AR HUD(head up display)原理 目标: 产业链上的各大Tier1及PGU企业都在积极开发这一技术,许多厂家已推出LCOS样机,比如说水晶光电、华阳集团、瀚思通、疆程已在北京车展或去年的上海车展上展出了LCOS方案的AR-HUD样…...
C/C++内存管理——内存泄漏/内存碎片
一、什么是内存泄漏 内存泄漏指的是在程序运行过程中,已经分配给程序使用的内存没有得到及时和正确的释放,导致这部分内存无法被程序再次使用或者被操作系统回收。内存泄漏通常发生在动态分配的内存上,如果这部分内存没有被正确释放,随着时间的推移,越来越多的内存将被占…...

使用 GaLore 预训练LLaMA-7B
项目代码: https://github.com/jiaweizzhao/galorehttps://github.com/jiaweizzhao/galore 参考博客: https://zhuanlan.zhihu.com/p/686686751 创建环境 基础环境配置如下: 操作系统: CentOS 7CPUs: 单个节点具有 1TB 内存的 Intel CP…...

OpenCV在图像上绘制文字示例
OpenCV计算机视觉开发实践:基于Qt C - 商品搜索 - 京东 OpenCV中除了提供绘制各种图形的函数外,还提供了一个特殊的绘制函数,用于在图像上绘制文字。这个函数是putText(),它是命名空间cv中的函数,其声明如下ÿ…...

猎板厚铜PCB工艺能力如何?
在电子产业向高功率、高集成化狂奔的今天,电路板早已不是沉默的配角。当5G基站、新能源汽车、工业电源等领域对电流承载、散热效率提出严苛要求时,一块能够“扛得住大电流、耐得住高温”的厚铜PCB,正成为决定产品性能的关键拼图。而在这条赛道…...
Java枚举类映射MySQL的深度解析与实践指南
Java枚举类映射MySQL的深度解析与实践指南 一、枚举类型映射的四大核心策略 1. 序数映射法(ordinal映射) 实现原理:存储枚举值的下标顺序 public enum OrderStatus {PENDING, // 存储为0PROCESSING, // 存储为1SHIPPED, //…...
Java并发编程哲学系列汇总
文章目录 并发编程基础并发编程进阶并发编程实践 并发编程基础 Java并发编程基础小结 Java线程池知识点小结 详解JUC包下各种锁的使用 并发编程利器Java CAS原子类全解 深入理解Java中的final关键字 Java并发容器深入解析:HashMap与ArrayList线程安全问题及解…...

Modbus转EtherNET IP网关开启节能改造新范式
在现代工业生产和能源管理中,无锡耐特森Modbus转EtherNET IP网关MCN-EN3001发挥着至关重要的作用。通过将传统的串行通信协议Modbus转换为基于以太网的EtherNET IP协议,这种网关设备不仅提高了数据传输的效率,而且为能源管理和控制系统的现代…...

TDengine 的 AI 应用实战——运维异常检测
作者: derekchen Demo数据集准备 我们使用公开的 NAB数据集 里亚马逊 AWS 东海岸数据中心一次 API 网关故障中,某个服务器上的 CPU 使用率数据。数据的频率为 5min,单位为占用率。由于 API 网关的故障,会导致服务器上的相关应用…...

tryhackme——Abusing Windows Internals(进程注入)
文章目录 一、Abusing Processes二、进程镂空三、线程劫持四、DLL注入五、Memory Execution Alternatives 一、Abusing Processes 操作系统上运行的应用程序可以包含一个或多个进程,进程表示正在执行的程序。进程包含许多其他子组件,并且直接与内存或虚…...

前端组件推荐 Swiper 轮播与 Lightbox 灯箱组件深度解析
在互联网产品不断迭代升级的今天,用户对于页面交互和视觉效果的要求越来越高。想要快速打造出吸睛又实用的项目,合适的组件必不可少。今天就为大家推荐两款超好用的组件 ——Swiper 轮播组件和 Lightbox 灯箱组件,轻松解决你的展示难题&#…...

Windows安装docker desktop
Windows 版本: Windows 10/11(64位)专业版、企业版或教育版(家庭版需手动配置)。 版本号需 ≥ 1909(建议更新到最新系统) 打开程序 启动服务后点点点 重启生效(没有的话 安装WSL…...
【优秀三方库研读】quill 开源库中的命名空间为什么要用宏封装
将命名空间封装成宏的作用与优势 QUILL_BEGIN_NAMESPACE 和 QUILL_END_NAMESPACE 这种宏封装是 C++ 库开发中的常见技巧,主要解决以下问题并提供显著优势: 1. 解决核心问题:命名空间嵌套与版本控制 问题场景: 库需要支持多版本共存(如 quill::v1, quill::v2),但希望默认…...