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("文档删除成功!");}
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AIGC8: 高通骁龙AIPC开发者大会记录B

图中是一个小男孩在市场卖他的作品。 AI应用开发出来之后&#xff0c;无论是个人开发者还是企业开发者。 如何推广分发是面临的大问题。 做出来的东西一定要符合商业规律。否则就是实验室里面的玩物&#xff0c;或者自嗨的东西。 背景 上次是回顾和思考前面两个硬件营销总的…

【JVM】类加载

1. 类加载过程 Java虚拟机&#xff08;JVM&#xff09;的 类加载 过程是将字节码文件&#xff08;.class文件&#xff09;从存储设备加载到内存&#xff0c;并为其创建相应的类对象的过程。类加载是Java程序运行的基础&#xff0c;保证了程序的动态性和安全性。JVM的类加载过程…

人工智能 | 基于ChatGPT开发人工智能服务平台

简介 ChatGPT 在刚问世的时候&#xff0c;其产品形态就是一个问答机器人。而基于ChatGPT的能力还可以对其做一些二次开发和拓展。比如模拟面试功能、或者智能机器人功能。 模拟面试功能包括个性化问题生成、实时反馈、多轮面试模拟、面试报告。 智能机器人功能提供24/7客服支…

将阮一峰老师的《ES6入门教程》的源码拷贝本地运行和发布

你好同学&#xff0c;我是沐爸&#xff0c;欢迎点赞、收藏、评论和关注。 阮一峰老师的《ES6入门教程》应该是很多同学学习 ES6 知识的重要参考吧&#xff0c;应该也有很多同学在看该文档的时候&#xff0c;想知道这个教程的前端源码是怎么实现的&#xff0c;也可能有同学下载…

esp32 wifi 联网后,用http 发送hello 用pc 浏览器查看网页

参考chatgpt Esp32可以配置为http服务器&#xff0c;可以socket编程。为了免除编写针对各种操作系统的app。完全可以用浏览器仿问esp32服务器&#xff0c;获取esp32的各种数据&#xff0c;甚至esp的音频&#xff0c;视频。也可以利用浏览器对esp进行各种操作。但esp不能主动仿…

【医学半监督】置信度指导遮蔽学习的半监督医学图像分割

摘要: 半监督学习(Semi-supervised learning)旨在利用少数标记数据和多数未标记数据训练出高性能模型。现有方法大多采用预测任务机制,在一致性或伪标签的约束下获得精确的分割图,但该机制通常无法克服确认偏差。针对这一问题,本文提出了一种用于半监督医学图像分割的新…

【C++笔记】C++编译器拷贝优化和内存管理

【C笔记】C编译器拷贝优化和内存管理 &#x1f525;个人主页&#xff1a;大白的编程日记 &#x1f525;专栏&#xff1a;C笔记 文章目录 【C笔记】C编译器拷贝优化和内存管理前言一.对象拷贝时的编译器优化二.C/C内存管理2.1练习2.2 C内存管理方式2.3 operator new与operator…

分布式锁优化之 使用lua脚本改造分布式锁保证判断和删除的原子性(优化之LUA脚本保证删除的原子性)

文章目录 1、lua脚本入门1.1、变量&#xff1a;弱类型1.2、流程控制1.3、在lua中执行redis指令1.4、实战&#xff1a;先判断是否自己的锁&#xff0c;如果是才能删除 2、AlbumInfoApiController --》testLock()3、AlbumInfoServiceImpl --》testLock() 1、lua脚本入门 Lua 教程…

长亭WAF绕过测试

本文的Bypass WAF 的核心思想在于&#xff0c;一些 WAF 产品处于降低误报考虑&#xff0c;对用户上传文件的内 容不做匹配&#xff0c;直接放行 0、环境 环境&#xff1a;两台服务器&#xff0c;一台配置宝塔面板&#xff0c;一台配置长亭雷池WAF 思路主要围绕&#xff1a;m…

Wpf使用NLog将日志输出到LogViewer

1 LogViewer LogViewer是通过UDP传输的高性能实时log查看器。 具有一下特性&#xff1a; 通过UDP读取日志通过文件导入日志导出日志到一个文件中排序、过滤&#xff08;日志树&#xff0c;日志等级&#xff09;和查找突出显示搜索文本从UPD接收日志时忽略IP地址列表多接收器支…

Java:Clonable 接口和拷贝

一 Clonable 接口 在 Java SE 中&#xff0c;Cloneable 是一个标记接口&#xff08;Marker Interface&#xff09;&#xff0c;它位于 java.lang 包中。这个接口的主要目的是标识实现该接口的类能够被合法地克隆&#xff08;即可以调用 Object 类中的 clone() 方法&#xff09…

【觅图网-注册安全分析报告-无验证方式导致安全隐患】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 1. 暴力破解密码&#xff0c;造成用户信息泄露 2. 短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉 3. 带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造…

神经网络面试题目

1. 批规范化(Batch Normalization)的好处都有啥&#xff1f;、 A. 让每一层的输入的范围都大致固定 B. 它将权重的归一化平均值和标准差 C. 它是一种非常有效的反向传播(BP)方法 D. 这些均不是 正确答案是&#xff1a;A 解析&#xff1a; ‌‌‌‌  batch normalization 就…

基于SpringBoot+WebSocket实现地图上绘制车辆实时运动轨迹图

实现基于北斗卫星的车辆定位和轨迹图的Maven工程&#xff08;使用模拟数据&#xff09;&#xff0c;我们将使用以下技术&#xff1a; Spring Boot&#xff1a;作为后端框架&#xff0c;用来提供数据接口。Thymeleaf&#xff1a;作为前端模板引擎&#xff0c;呈现网页。Leaflet…

算法之逻辑斯蒂回归(Logistic regression)

简介&#xff1a;个人学习分享&#xff0c;如有错误&#xff0c;欢迎批评指正。 逻辑斯蒂回归&#xff08;Logistic Regression&#xff09;是统计学中一种广泛应用于二分类问题的算法。它的主要目标是预测二分类问题中的事件发生的概率。尽管名字里有“回归”&#xff0c;但逻…

高级I/O知识分享【epoll || Reactor ET,LT模式】

博客主页&#xff1a;花果山~程序猿-CSDN博客 文章分栏&#xff1a;Linux_花果山~程序猿的博客-CSDN博客 关注我一起学习&#xff0c;一起进步&#xff0c;一起探索编程的无限可能吧&#xff01;让我们一起努力&#xff0c;一起成长&#xff01; 目录 一&#xff0c;接口 epo…

【kaggle竞赛】毒蘑菇的二元预测题目相关信息和思路求解代码

毒蘑菇的二元预测 您提供了很多关于不同二元分类任务的资源和链接&#xff0c;看起来这些都是Kaggle竞赛中的参考资料和高分解决方案。为了帮助您更好地利用这些资源&#xff0c;这里是一些关键点的总结&#xff1a; Playground Season 4 Episode 8 主要关注的竞赛: 使用银行…

如何将很多个pdf拼接在一起?很多种PDF拼接的方法

如何将很多个pdf拼接在一起&#xff1f;将多个PDF文件合并不仅能够提升信息的整合性&#xff0c;还能使文件管理更加高效。想象一下&#xff0c;你需要向同事或老师提交一份综合报告&#xff0c;其中包含了多份相关资料。如果每个文件单独存在&#xff0c;查找和传输都会变得繁…

Java 入门指南:JVM(Java虚拟机)—— Java 类加载器详解

类加载器 类加载器&#xff08;Class Loader&#xff09;是 Java 虚拟机&#xff08;JVM&#xff09;的一部分&#xff0c;它的作用是将类的字节码文件&#xff08;.class 文件&#xff09;从磁盘或其他来源加载到 JVM 中。类加载器负责查找和加载类的字节码文件&#xff0c;并…

Python|OpenCV-实现识别目标图像中的圆圈(20)

前言 本文是该专栏的第22篇,后面将持续分享OpenCV计算机视觉的干货知识,记得关注。 在处理图像检测项目的时候,可能会遇到需要检测目标图像中的“圆圈”需求。笔者在这里举个例子,如下图所示: 在图中有一个篮球,但是我们要找的目标对象并不是篮球,而是篮球它本身的这个…