1、Elasticsearch
The Elastic Stack, 包括 Elasticsearch、Kibana、Beats 和 Logstash(也称为 ELK Stack)。能够安全可靠地获取任何来源、任何格式的数据,然后实时地对数据进行搜索、分析和可视化。Elaticsearch,简称为 ES,ES 是一个**开源的高扩展的分布式全文搜索引擎,**是整个 Elastic Stack 技术栈的核心。它可以近乎实时的存储、检索数据;本身扩展性很好,可以扩展到上百台服务器,处理 PB 级别的数据。
-
开源、免费:基于Apache License 2.0开源协议,并且完全免费。
-
基于Java语言:Elasticsearch基于Java语言开发,运行在Jvm环境中。
-
**基于Lucene框架:**基于开源的Apache Lucene框架开发。
-
原生分布式:不依赖与Zookeeper,自带分布式解决方案。
-
高性能 :支持海量数据的全文检索。支持PB级数据秒内响应 !对于ES来说,上亿级别数据只不过是起点!性能几乎没有上限,足以满足各种对性能要求极高的场景。
-
可伸缩:弹性搜索,可根据不同规模服务对性能需要的不同而动态扩展或收缩性能。
-
易扩展:支持非常方便的横向扩展集群。
-
开箱即用 :对于小公司,解压后零配置启动服务即可立即使用,门槛极低
-
跨编程语言:支持Java、Golang、Python、C#、PHP等多种变成语言,几乎所有语言开发者都可以使用Elasticsearch。
1.1、全文搜索引擎
Google,百度类的网站搜索,它们都是根据网页中的关键字生成索引,我们在搜索的时候输入关键字,它们会将该关键字即索引匹配到的所有网页返回;还有常见的项目中应用日志的搜索等等。对于这些非结构化的数据文本,关系型数据库搜索不是能很好的支持。一般传统数据库,全文检索都实现的很鸡肋,因为一般也没人用数据库存文本字段。进行全文检索需要扫描整个表,如果数据量大的话即使对 SQL 的语法优化,也收效甚微。建立了索引,但是维护起来也很麻烦,对于 insert 和 update 操作都会重新构建索引。基于以上原因可以分析得出,在一些生产环境中,使用常规的搜索方式,性能是非常差
的:
-
搜索的数据对象是大量的非结构化的文本数据。
-
文件记录量达到数十万或数百万个甚至更多。
-
支持大量基于交互式文本的查询。
-
需求非常灵活的全文搜索查询。
-
对高度相关的搜索结果的有特殊需求,但是没有可用的关系数据库可以满足。
-
对不同记录类型、非文本数据操作或安全事务处理的需求相对较少的情况。
为了解决结构化数据搜索和非结构化数据搜索性能问题,我们就需要专业,健壮,强大的全文搜索引擎这里说到的全文搜索引擎指的是目前广泛应用的主流搜索引擎。它的工作原理是计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。这个过程类似于通过字典中的检索字表查字的过程。
Elasticsearch 分为 Linux 和 Windows 版本,基于我们主要学习的是 Elasticsearch 的 Java客户端的使用,所以课程中使用的是安装较为简便的 Windows 版本。
1.2、windows下安装
是这样的,Elasticsearch从7.0版本开始就开始i使用内置得jdk,所以对于没有装过jdk的直接解压也是可以用的,然后随着版本的迭代,然后对于内置的jdk的版也随之升级,8.0之后的版本好像是内置jdk17
下载的话直接到官网下载windows版本的就可以,然后解压,到这里其实是没有什么问题的,一切都是ok的,但是在后续的操作中出现了好多的问题,确实是开箱即用但是由于我们的电脑上一般都安装的由jdk,并且配置的过环境变量。
然后启动的时候确实会显示忽略本地的jdk,然后就一直启动不成功,气死人!!!我找网上的教程然后都在说直接解压然后双击Elasticsearch.bat就可以直接的启动,然后访问localhost:9200然后既可以显示版本信息之类的。但是我就是死活启动不了,当然其中也其他的问题,比如启动的时候控制台打印的日志乱码等等
首先说一下无法启动的事情,提示的信息是什么来着,操!大概是........\lib\tools.jar找不到!然后就很纳闷别人都可以,为什么我不可以!然后各种找教程,但是大部分人都没有遇见这个问题!
这个无法启动的原因就是配置了classpath然后导致无法启动报错结局方式也很简单就是把这个系统的环境变量删除就可以啦!
CLASSPATH
.;%java_home%\lib;%java_home%\lib\tools.jar
对于控制台乱码在jvm.options文件中添加以下代码
-Dfile.encoding=GBK
介绍下目录结构
目录 | 含义 |
---|---|
bin | 可执行脚本目录 |
config | 配置目录 |
jdk | 内置jdk目录 |
lib | 类库 |
logs | 日志目录 |
modules | 模块目录 |
plugins | 插件目录 |
启动进入 bin 文件目录,点击 elasticsearch.bat 文件启动 ES 服务,注意: 9300 端口为 Elasticsearch 集群间组件的通信端口, 9200 端口为浏览器访问的 http协议 RESTful端口 。http://localhost:9200
如果双击启动窗口闪退,通过路径访问追踪错误,如果是"空间不足",请修改config/jvm.options 配置文件。当然也可以查看log日志看具体的报错的原因。
# 设置 JVM 初始内存为 1G。此值可以设置与-Xmx 相同,以避免每次垃圾回收完成后 JVM 重新分配内存
# Xms represents the initial size of total heap space
# 设置 JVM 最大可用内存为 1G
# Xmx represents the maximum size of total heap space
-Xms1g
-Xmx1g

这里说一下哦,8.0以后的版本的配置文件中开启的登录验证,也就是说初次访问显示无法方法问的同学可以修改配置文件中以下配置,另外刚开始打开的配置文件是注释状态(没有高亮),这时候你只要启动后就有高亮显示,然后将运行的程序先停掉,对啦打印的东西要保存以下哦
-> Elasticsearch security features have been automatically configured!
-> Authentication is enabled and cluster connections are encrypted.
-> Password for the elastic user (reset with `bin/elasticsearch-reset-password -u elastic`):
zaWETn2G5Mu6FcVqiAwL
-> HTTP CA certificate SHA-256 fingerprint:
6d67bb3606c4b5abc202e9790e22aac7941803b2bfed8d7b330358a0153cf89b
-> Configure Kibana to use this cluster:
* Run Kibana and click the configuration link in the terminal when Kibana starts.
* Copy the following enrollment token and paste it into Kibana in your browser (valid for the next 30 minutes):
eyJ2ZXIiOiI4LjEwLjIiLCJhZHIiOlsiMTkyLjE2OC4xLjI6OTIwMCJdLCJmZ3IiOiI2ZDY3YmIzNjA2YzRiNWFiYzIwMmU5NzkwZTIyYWFjNzk0MTgwM2IyYmZlZDhkN2IzMzAzNThhMDE1M2NmODliIiwia2V5IjoiMzVfT1o0MEJlMEtZcFB2NHQ3UFo6SGlUbksyaElSLWVSaVhBekREeVp5ZyJ9
-> Configure other nodes to join this cluster:
* On this node:
- Create an enrollment token with `bin/elasticsearch-create-enrollment-token -s node`.
- Uncomment the transport.host setting at the end of config/elasticsearch.yml.
- Restart Elasticsearch.
* On other nodes:
- Start Elasticsearch with `bin/elasticsearch --enrollment-token <token>`, using the enrollment token that you generated.
然后将程序停止可以使用CTRL+C,修改配置文件

一个是允许发送http请求,一个是关闭密码登录的,重新启动后访问就可以正常的访问了!
1.3、数据存储格式
如果直接通过浏览器向 Elasticsearch 服务器发请求,那么需要在发送的请求中包含HTTP 标准的方法,而 HTTP 的大部分特性且仅支持 GET 和 POST 方法。所以为了能方便地进行客户端的访问,可以使用 Postman 软件
Elasticsearch 是面向文档型数据库,一条数据在这里就是一个文档。为了方便大家理解,将 Elasticsearch 里存储文档数据和关系型数据库 MySQL 存储数据的概念进行一个类比ES 里的 Index 可以看做一个库,而 Types 相当于表,Documents 则相当于表的行。这里 Types 的概念已经被逐渐弱化,Elasticsearch 6.X 中,一个 index 下已经只能包含一个type,Elasticsearch 7.X 中, Type 的概念已经被删除了。

2、 HTTP 操作
2.1、 索引操作
2.1.1、创建索引
对比关系型数据库,创建索引就等同于创建数据库,在 Postman 中,向 ES 服务器发 PUT 请求 :http://127.0.0.1:9200/shopping
{
"acknowledged"【响应结果】: true, # true 操作成功
"shards_acknowledged"【分片结果】: true, # 分片操作成功
"index"【索引名称】: "shopping"
}
# 注意:创建索引库的分片数默认 1 片,在 7.0.0 之前的 Elasticsearch 版本中,默认 5 片
如果重复添加索引,会返回错误信息
{
"error": {
"root_cause": [
{
"type": "resource_already_exists_exception",
"reason": "index [shopping/pUOQECitSKeaTeG4oT5vFg] already exists",
"index_uuid": "pUOQECitSKeaTeG4oT5vFg",
"index": "shopping"
}
],
"type": "resource_already_exists_exception",
"reason": "index [shopping/pUOQECitSKeaTeG4oT5vFg] already exists",
"index_uuid": "pUOQECitSKeaTeG4oT5vFg",
"index": "shopping"
},
"status": 400
}
2.1.2、查询单个索引
在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/shopping
{
"shopping"【索引名】: {
"aliases"【别名】: {},
"mappings"【映射】: {},
"settings"【设置】: {
"index"【设置-索引】: {
"routing": {
"allocation": {
"include": {
"_tier_preference": "data_content"
}
}
},
"number_of_shards【设置-索引-主分片数量】": "1",
"provided_name【设置-索引-名称】": "shopping",
"creation_date【设置-索引-创建时间】": "1706844440345",
"number_of_replicas【设置-索引-副分片数量】": "1",
"uuid【设置-索引-唯一标示】": "pUOQECitSKeaTeG4oT5vFg",
"version【设置-索引-版本】": {
"created": "8100299"
}
}
}
}
}
2.1.3、查看所有索引
在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/_cat/indices?v,这里请求路径中的_cat 表示查看的意思,indices 表示索引,所以整体含义就是查看当前 ES服务器中的所有索引,就好像 MySQL 中的 show tables 的感觉,服务器响应结果如下。

表头 | 含义 |
---|---|
health | 当前服务器健康状态:green (集群完整) yellow(单点正常、集群不完整) red(单点不正常) |
status | 索引打开、关闭状态 |
index | 索引名 |
uuid | 索引统一编号 |
pri | 主分片数量 |
rep | 副本数量 |
docs.count | 可用文档数量 |
docs.deleted | 文档删除状态(逻辑删除) |
store.size | 主分片和副分片整体占空间大小 |
pri.store.size | 主分片占空间大小 |
2.1.4、删除索引
在 Postman 中,向 ES 服务器发 DELETE 请求 :http://127.0.0.1:9200/shopping
{
"acknowledged": true
}
再次发送请求的响应结果,提示没有发现索引
{
"error": {
"root_cause": [
{
"type": "index_not_found_exception",
"reason": "no such index [shopping]",
"resource.type": "index_or_alias",
"resource.id": "shopping",
"index_uuid": "_na_",
"index": "shopping"
}
],
"type": "index_not_found_exception",
"reason": "no such index [shopping]",
"resource.type": "index_or_alias",
"resource.id": "shopping",
"index_uuid": "_na_",
"index": "shopping"
},
"status": 404
}
2.2、文档操作
2.2.1、创建文档
索引已经创建好了,接下来我们来创建文档,并添加数据。这里的文档可以类比为关系型数据库中的表数据,添加的数据格式为 JSON 格式在 Postman 中,向 ES 服务器发 POST 请求 :http://127.0.0.1:9200/shopping/_doc
请求体内容为:
{
"title":"小米手机",
"category":"小米",
"images":"https://n.sinaimg.cn/sinakd20121/303/w913h990/20220725/fe6f-e35036e8bbb937daefa8c639736afe28.jpg",
"price":3999.00
}
此处发送请求的方式必须为 POST ,不能是 PUT,否则会发生错误
{
"_index"【索引】: "shopping",
"_id"【唯一标识】: "VXoWaI0BKYUO8Qon9BKh", #可以类比为 MySQL 中的主键,随机生成
"_version"【版本】: 1,
"result"【结果】: "created",#这里的 create 表示创建成功
"_shards"【分片】: {
"total"【分片 - 总数】: 2,
"successful"【分片 - 成功】: 1,
"failed"【分片 - 失败】: 0
},
"_seq_no": 0,
"_primary_term": 1
}
上面的数据创建后,由于没有指定数据唯一性标识(ID),默认情况下,ES 服务器会随机生成一个。如果想要自定义唯一性标识,需要在创建时指定:http://127.0.0.1:9200/shopping/_doc/1
{
"title":"小米13",
"category":"小米",
"images":"https://cdn.cnbj1.fds.api.mi-img.com/product-images/xiaomi-13kb7buy/8660.png?x-fds-process=image/resize,q_90,f_webp",
"price":2999.00
}
响应结果
{
"_index": "shopping",
"_id": "1",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 1,
"_primary_term": 1
}
此处需要注意:如果增加数据时明确数据主键,那么请求方式也可以为 PUT
2.2.2、查看文档(单个)
查看文档时,需要指明文档的唯一性标识,类似于 MySQL 中数据的主键查询在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/shopping/_doc/1
查询成功后,服务器响应结果:
{
"_index"【索引】: "shopping",
"_id": "1",
"_version": 1,
"_seq_no": 1,
"_primary_term": 1,
"found"【查询结果】: true, # true 表示查找到,false 表示未查找到
"_source"【文档源信息】: {
"title": "小米13",
"category": "小米",
"images": "https://cdn.cnbj1.fds.api.mi-img.com/product-images/xiaomi-13kb7buy/8660.png?x-fds-process=image/resize,q_90,f_webp",
"price": 2999.00
}
}
2.2.3、查询所有的文档
在postman中发送GET 请求 http://127.0.0.1:9200/shopping/_search
请求成功结果
{
"took"【耗时】: 14,
"timed_out【是否超时】": false,
"_shards"【转台你信息】: {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits"【命中信息】: {
"total": {
"value": 7,
"relation": "eq"
},
"max_score": 1.0,
"hits"【命中结果】: [
{
"_index": "shopping",
"_id": "VXoWaI0BKYUO8Qon9BKh",
"_score": 1.0,
"_source": {
"title": "小米手机",
"category": "小米",
"images": "https://n.sinaimg.cn/sinakd20121/303/w913h990/20220725/fe6f-e35036e8bbb937daefa8c639736afe28.jpg",
"price": 3999.00
}
},
{
"_index": "shopping",
"_id": "3",
"_score": 1.0,
"_source": {
"title": "红米13",
"category": "小米",
"images": "http://www.baidu.com/",
"price": 4990.00
}
},
{
"_index": "shopping",
"_id": "4",
"_score": 1.0,
"_source": {
"title": "黑米14",
"category": "小米",
"images": "http://www.baidu.com/",
"price": 5990.00
}
},
{
"_index": "shopping",
"_id": "5",
"_score": 1.0,
"_source": {
"title": "小幸子",
"category": "小李",
"images": "http://www.baidu.com/",
"price": 9999.00
}
},
{
"_index": "shopping",
"_id": "6",
"_score": 1.0,
"_source": {
"title": "华为60p",
"category": "华为",
"images": "http://www.baidu.com/",
"price": 6999.00
}
},
{
"_index": "shopping",
"_id": "7",
"_score": 1.0,
"_source": {
"title": "华为nove",
"category": "华为",
"images": "http://www.baidu.com/",
"price": 4999.00
}
},
{
"_index": "shopping",
"_id": "8",
"_score": 1.0,
"_source": {
"title": "魅族21pro",
"category": "魅族",
"images": "http://www.baidu.com/",
"price": 6999.00
}
}
]
}
}
2.2.4、修改文档
和新增文档一样,输入相同的 URL 地址请求,如果请求体变化,会将原有的数据内容覆盖在 Postman 中,向 ES 服务器发 POST 请求 :http://127.0.0.1:9200/shopping/_doc/1
请求体内容为:
{
"title":"华为手机",
"category":"华为",
"images":"https://consumer.huawei.com/content/dam/huawei-cbg-site/cn/mkt/pdp/phones/mate60-pro/img/kv/sellpoint-4@2x.webp",
"price":4999.00
}
修改成功后,服务器响应结果:
{
"_index": "shopping",
"_id": "1",
"_version"【版本】: 2,
"result"【结果】: "updated",# updated 表示数据被更新
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 2,
"_primary_term": 1
}
2.2.4、修改字段
修改数据时,也可以只修改某一给条数据的局部信息,在 Postman 中,向 ES 服务器发 POST 请求 :http://127.0.0.1:9200/shopping/_update/1
请求体内容为:
{
"doc": {
"price":3000.00
}
}
修改成功后,服务器响应结果:
{
"_index": "shopping",
"_id": "1",
"_version": 3,
"result": "updated",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 3,
"_primary_term": 1
}
根据唯一性标识,查询文档数据,文档数据已经更新
{
"_index": "shopping",
"_id": "1",
"_version": 3,
"_seq_no": 3,
"_primary_term": 1,
"found": true,
"_source": {
"title": "华为手机",
"category": "华为",
"images": "https://consumer.huawei.com/content/dam/huawei-cbg-site/cn/mkt/pdp/phones/mate60-pro/img/kv/sellpoint-4@2x.webp",
"price": 8999.0
}
}
2.2.5、删除文档
删除一个文档不会立即从磁盘上移除,它只是被标记成已删除(逻辑删除)。在 Postman 中,向 ES 服务器发 DELETE 请求 :http://127.0.0.1:9200/shopping/_doc/1
删除成功,服务器响应结果:
{
"_index": "shopping",
"_id": "1",
"_version"【版本】: 4,#对数据的操作,都会更新版本
"result【结果】": "deleted",# deleted 表示数据被标记为删除
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 4,
"_primary_term": 1
}
删除后再查询当前文档信息
{
"_index": "shopping",
"_id": "1",
"found": false
}
如果删除一个并不存在的文档
{
"_index": "shopping",
"_id": "1111111",
"_version": 1,
"result": "not_found",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 5,
"_primary_term": 1
}
2.2.6、条件删除文档
一般删除数据都是根据文档的唯一性标识进行删除,实际操作时,也可以根据条件对多条数
据进行删除
首先分别增加多条数据:
{
"title":"小米11",
"category":"小米",
"images":"http://www.baidu.com/",
"price":2990.00
}
{
"title":"大米12",
"category":"小米",
"images":"http://www.baidu.com/",
"price":3400.00
}
{
"title":"红米13",
"category":"小米",
"images":"http://www.baidu.com/",
"price":4990.00
}
{
"title":"黑米14",
"category":"小米",
"images":"http://www.baidu.com/",
"price":5990.00
}
{
"title":"小幸子",
"category":"小李",
"images":"http://www.baidu.com/",
"price":9999.00
}
{
"title":"华为60p",
"category":"华为",
"images":"http://www.baidu.com/",
"price":6999.00
}
{
"title":"华为nove",
"category":"华为",
"images":"http://www.baidu.com/",
"price":4999.00
}
{
"title":"魅族21pro",
"category":"魅族",
"images":"http://www.baidu.com/",
"price":6999.00
}
向 ES 服务器发 POST 请求 :http://127.0.0.1:9200/shopping/_delete_by_query
请求体内容为:
{
"query":{
"match":{
"price":3400.0
}
}
}
删除成功后,服务器响应结果:
{
"took"【耗时】: 194,
"timed_out"【是否超时】: false,
"total"【总数】: 2,
"deleted"【删除数量】: 2,
"batches": 1,
"version_conflicts": 0,
"noops": 0,
"retries": {
"bulk": 0,
"search": 0
},
"throttled_millis": 0,
"requests_per_second": -1.0,
"throttled_until_millis": 0,
"failures": []
}
2.2.7、条件查询(请求地址)
其实就是在全查询中设置一些过滤条件,在postman中发送GET 请求:http://127.0.0.1:9200/shopping/_search?q=category:小米
{
"took": 4,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 4,
"relation": "eq"
},
"max_score": 1.0286198,
"hits": [
{
"_index": "shopping",
"_id": "VXoWaI0BKYUO8Qon9BKh",
"_score": 1.0286198,
"_source": {
"title": "小米手机",
"category": "小米",
"images": "https://n.sinaimg.cn/sinakd20121/303/w913h990/20220725/fe6f-e35036e8bbb937daefa8c639736afe28.jpg",
"price": 3999.00
}
},
{
"_index": "shopping",
"_id": "3",
"_score": 1.0286198,
"_source": {
"title": "红米13",
"category": "小米",
"images": "http://www.baidu.com/",
"price": 4990.00
}
},
{
"_index": "shopping",
"_id": "4",
"_score": 1.0286198,
"_source": {
"title": "黑米14",
"category": "小米",
"images": "http://www.baidu.com/",
"price": 5990.00
}
},
{
"_index": "shopping",
"_id": "5",
"_score": 0.4307829,
"_source": {
"title": "小幸子",
"category": "小李",
"images": "http://www.baidu.com/",
"price": 9999.00
}
}
]
}
}
2.2.8、条件查询(请求体)
请求体改为以请求体的方式进行传递,GET 请求:http://127.0.0.1:9200/shopping/_search
请求体
{
"query":{
"match":{
"category":"小米"
}
}
}
#当请求的方式不变,改变请求体中的内容
{
"query":{
"match_all":{
//没有请求参数就是全量查询
}
}
}
响应结果
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 4,
"relation": "eq"
},
"max_score": 1.0286198,
"hits": [
{
"_index": "shopping",
"_id": "VXoWaI0BKYUO8Qon9BKh",
"_score": 1.0286198,
"_source": {
"title": "小米手机",
"category": "小米",
"images": "https://n.sinaimg.cn/sinakd20121/303/w913h990/20220725/fe6f-e35036e8bbb937daefa8c639736afe28.jpg",
"price": 3999.00
}
},
{
"_index": "shopping",
"_id": "3",
"_score": 1.0286198,
"_source": {
"title": "红米13",
"category": "小米",
"images": "http://www.baidu.com/",
"price": 4990.00
}
},
{
"_index": "shopping",
"_id": "4",
"_score": 1.0286198,
"_source": {
"title": "黑米14",
"category": "小米",
"images": "http://www.baidu.com/",
"price": 5990.00
}
},
{
"_index": "shopping",
"_id": "5",
"_score": 0.4307829,
"_source": {
"title": "小幸子",
"category": "小李",
"images": "http://www.baidu.com/",
"price": 9999.00
}
}
]
}
}
2.2.9、分页查询
发送GET 请求,http://127.0.0.1:9200/shopping/_search
请求体:
{
"query":{
"match_all":{
}
},
"from":0,//当前页数据的起始位置
"size":2,//一页多少数据
"_source":["title"],//指定查询的结果
}
响应结果
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 7,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "shopping",
"_id": "VXoWaI0BKYUO8Qon9BKh",
"_score": 1.0,
"_source": {
"title": "小米手机",
"category": "小米",
"images": "https://n.sinaimg.cn/sinakd20121/303/w913h990/20220725/fe6f-e35036e8bbb937daefa8c639736afe28.jpg",
"price": 3999.00
}
},
{
"_index": "shopping",
"_id": "3",
"_score": 1.0,
"_source": {
"title": "红米13",
"category": "小米",
"images": "http://www.baidu.com/",
"price": 4990.00
}
}
]
}
}
2.2.10、排序
发送GET 请求,http://127.0.0.1:9200/shopping/_search
请求体:
{
"query":{
"match_all":{
}
},
"from":0,
"size":2,
"_source":["title"],
"sort":{
"price"【排序的字段】:{
"order"【排序规则】:"desc"
}
}
}
请求结果
{
"took": 18,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 7,
"relation": "eq"
},
"max_score": null,
"hits": [
{
"_index": "shopping",
"_id": "5",
"_score": null,
"_source": {
"title": "小幸子"
},
"sort": [
9999.0
]
},
{
"_index": "shopping",
"_id": "6",
"_score": null,
"_source": {
"title": "华为60p"
},
"sort": [
6999.0
]
}
]
}
}
2.2.11、多条件查询
请求GET:http://127.0.0.1:9200/shopping/_search
请求体:
{
"query": {
"bool"【查询条件】: {
"must"【类似and,下面的条件必须成立】: [
{//条件2
"match"【匹配规则】: {
"category": "小米"
}
},
{//条件1
"match": {
"price":5990.0
}
}
]
}
},
"from": 0,
"size": 5,
"_source": [
"title"
],
"sort": {
"price": {
"order": "desc"
}
}
}
请求结果
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": null,
"hits": [
{
"_index": "shopping",
"_id": "4",
"_score": null,
"_source": {
"title": "黑米14"
},
"sort": [
5990.0
]
}
]
}
}
当然也可以使用or
请求体
{
"query": {
"bool": {
"should": [
{
"match": {
"category": "小米"
}
},
{
"match": {
"category": "魅族"
}
}
]
}
},
"from": 0,
"size": 5,
"_source": [
"title"
],
"sort": {
"price": {
"order": "desc"
}
}
}
响应结果
{
"took": 3,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 5,
"relation": "eq"
},
"max_score": null,
"hits": [
{
"_index": "shopping",
"_id": "5",
"_score": null,
"_source": {
"title": "小幸子"
},
"sort": [
9999.0
]
},
{
"_index": "shopping",
"_id": "8",
"_score": null,
"_source": {
"title": "魅族21pro"
},
"sort": [
6999.0
]
},
{
"_index": "shopping",
"_id": "4",
"_score": null,
"_source": {
"title": "黑米14"
},
"sort": [
5990.0
]
},
{
"_index": "shopping",
"_id": "3",
"_score": null,
"_source": {
"title": "红米13"
},
"sort": [
4990.0
]
},
{
"_index": "shopping",
"_id": "VXoWaI0BKYUO8Qon9BKh",
"_score": null,
"_source": {
"title": "小米手机"
},
"sort": [
3999.0
]
}
]
}
}
2.2.12、多条件查询过滤
发送请求GET,
请求体
{
"query": {
"bool": {
"should": [
{
"match": {
"category": "小米"
}
},
{
"match": {
"category": "华为"
}
},
{
"match": {
"category": "魅族"
}
}
],
"filter":{
"range":{
"price":{
"gt":5000
}
}
}
}
},
"from": 0,
"size": 5,
"_source": [
"title"
],
"sort": {
"price": {
"order": "desc"
}
}
}
响应参数
{
"took": 12,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 4,
"relation": "eq"
},
"max_score": null,
"hits": [
{
"_index": "shopping",
"_id": "5",
"_score": null,
"_source": {
"title": "小幸子"
},
"sort": [
9999.0
]
},
{
"_index": "shopping",
"_id": "6",
"_score": null,
"_source": {
"title": "华为60p"
},
"sort": [
6999.0
]
},
{
"_index": "shopping",
"_id": "8",
"_score": null,
"_source": {
"title": "魅族21pro"
},
"sort": [
6999.0
]
},
{
"_index": "shopping",
"_id": "4",
"_score": null,
"_source": {
"title": "黑米14"
},
"sort": [
5990.0
]
}
]
}
}
2.2.13、全文查询+高亮
是这样的,比如我们查询的小米,然后查询的时候会将"小"和"米",查询的结果可能是小米,小李,小花,大米,红米,黑米等等。那么现在就是想换需求了,按照我的关键字严格的匹配,如何写查询的请求体呐!
发送GET:
请求体:
{
"query":{
"match_phrase":{
"category":"小李"
}
},
"highlight":{
"fields":{
"category":{}
}
}
}
响应参数:
{
"took": 11,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 2.3279026,
"hits": [
{
"_index": "shopping",
"_id": "5",
"_score": 2.3279026,
"_source": {
"title": "小幸子",
"category": "小李",
"images": "http://www.baidu.com/",
"price": 9999.00
},
"highlight": {
"category": [
"<em>小李</em>"
]
}
}
]
}
}
2.2.14、聚合操作-分组
请求方式GET:http://127.0.0.1:9200/shopping/_search
请求体
{
"aggs": { //聚合操作
"price_group": { //名称。随意起名
"terms": { //分组
"field": "price" //分组字段
}
}
},
"size":0//不显示原始数据
}
响应结果:
{
"took": 25,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 7,
"relation": "eq"
},
"max_score": null,
"hits": []
},
"aggregations": {
"price_group": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": 6999.0,
"doc_count": 2
},
{
"key": 3999.0,
"doc_count": 1
},
{
"key": 4990.0,
"doc_count": 1
},
{
"key": 4999.0,
"doc_count": 1
},
{
"key": 5990.0,
"doc_count": 1
},
{
"key": 9999.0,
"doc_count": 1
}
]
}
}
}
2.2.15、聚合操作-平均值
请求方式GET:http://127.0.0.1:9200/shopping/_search
请求体
{
"aggs": { //聚合操作
"price_avg": { //名称。随意起名
"avg": { //平均值
"field": "price" //平均值字段
}
}
},
"size":0//不显示原始数据
}
响应参数
{
"took": 11,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 7,
"relation": "eq"
},
"max_score": null,
"hits": []
},
"aggregations": {
"price_avg": {
"value": 6282.142857142857
}
}
}
2.3、映射操作
有了索引库,等于有了数据库中的 database。接下来就需要建索引库(index)中的映射了,类似于数据库(database)中的表结构(table)。创建数据库表需要设置字段名称,类型,长度,约束等;索引库也一样,需要知道这个类型下有哪些字段,每个字段有哪些约束信息,这就叫做映射(mapping)。
2.3.1、创建映射
在 Postman 中,向 ES 服务器发 PUT 请求 :http://127.0.0.1:9200/student/_mapping
请求体内容为:
{
"properties": {
"name": {
"type": "text",
"index": true
},
"sex": {
"type": "text",
"index": false
},
"age": {
"type": "long",
"index": false
}
}
}
响应结果
{
"acknowledged": true
}
先创建索引,然后才可以创建映射不然会提示索引不存在的情况
映射数据说明:
-
字段名:任意填写,下面指定许多属性,例如:title、subtitle、images、price
-
type:类型,Elasticsearch 中支持的数据类型非常丰富,说几个关键的:
-
String 类型,又分两种:
-
text:可分词
-
keyword:不可分词,数据会作为完整字段进行匹配
-
-
Numerical:数值类型,分两类
-
基本数据类型:long、integer、short、byte、double、float、half_float
-
浮点数的高精度类型:scaled_float
-
-
Date:日期类型
-
Array:数组类型
-
Object:对象
-
-
index:是否索引,默认为 true,也就是说你不进行任何配置,所有字段都会被索引。
-
true:字段会被索引,则可以用来进行搜索
-
false:字段不会被索引,不能用来搜索
-
-
store:是否将数据进行独立存储,默认为 false,原始的文本会存储在source 里面,默认情况下其他提取出来的字段都不是独立存储的,是从source 里面提取出来的。当然你也可以独立的存储某个字段,只要设置"store": true 即可,获取独立存储的字段要比从_source 中解析快得多,但是也会占用更多的空间,所以要根据实际业务需求来设置。
-
analyzer:分词器,这里的 ik_max_word 即使用 ik 分词器,后面会有专门的章节学习
2.3.2、查看映射
在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_mapping
响应结果:
{
"student": {
"mappings": {
"properties": {
"age": {
"type": "long",
"index": false
},
"name": {
"type": "text"
},
"sex": {
"type": "text",
"index": false
}
}
}
}
}
2.3.3、高级查询
Elasticsearch 提供了基于 JSON 提供完整的查询 DSL 来定义查询
# POST /student/_doc/1001
{
"name":"zhangsan",
"nickname":"zhangsan",
"sex":"男",
"age":30
}
# POST /student/_doc/1002
{
"name":"lisi",
"nickname":"lisi",
"sex":"男",
"age":20
}
# POST /student/_doc/1003
{
"name":"wangwu",
"nickname":"wangwu",
"sex":"女",
"age":40
}
# POST /student/_doc/1004
{
"name":"zhangsan1",
"nickname":"zhangsan1",
"sex":"女",
"age":50
}
# POST /student/_doc/1005
{
"name":"zhangsan2",
"nickname":"zhangsan2",
"sex":"女",
"age":30
}
2.3.3.1查询所有文档
在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search
{
"query": {
"match_all": {}
}
}
# "query":这里的 query 代表一个查询对象,里面可以有不同的查询属性
# "match_all":查询类型,例如:match_all(代表查询所有), match,term , range 等等
# {查询条件}:查询条件会根据类型的不同,写法也有差异
2.3.3.2、匹配查询
match 匹配类型查询,会把查询条件进行分词,然后进行查询,多个词条之间是 or 的关系在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search
{
"query":{
"match":{
"name":"zhangsan"
}
}
}
2.3.3.3、字段匹配查询
multi_match 与 match 类似,不同的是它可以在多个字段中查询。在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search
{
"query": {
"multi_match": {
"query": "zhangsan",
"fields": ["name","nickname"]
}
}
}
2.3.3.4、关键字精确查询
term 查询,精确的关键词匹配查询,不对查询条件进行分词。在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search
{
"query": {
"term": {
"name": {
"value": "zhangsan"
}
}
}
}
2.3.3.5、多关键字精确查询
terms 查询和 term 查询一样,但它允许你指定多值进行匹配。如果这个字段包含了指定值中的任何一个值,那么这个文档满足条件,类似于 mysql 的 in在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search
{
"query": {
"terms": {
"name": [
"zhangsan",
"lisi"
]
}
}
}
2.3.3.6、指定查询字段
默认情况下,Elasticsearch 在搜索的结果中,会把文档中保存在source 的所有字段都返回。如果我们只想获取其中的部分字段,我们可以添加 source 的过滤在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search
{
"query": {
"terms": {
"name": [
"zhangsan"
]
}
},
"_source": [
"name",
"nickname"
]
}
2.3.3.6、过滤字段
我们也可以通过:
-
includes:来指定想要显示的字段
-
excludes:来指定不想要显示的字段
在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search
{
"_source": {
"includes": [
"name",
"nickname"
]
},
"query": {
"terms": {
"name": [
"zhangsan"
]
}
}
}
{
"_source": {
"excludes": [
"name",
"nickname"
]
},
"query": {
"terms": {
"nickname": [
"zhangsan"
]
}
}
}
2.3.3.7、组合查询
bool
把各种其它查询通过must
(必须 )、must_not
(必须不)、should
(应该)的方式进行组合在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "zhangsan"
}
}
],
"must_not": [
{
"match": {
"age": "40"
}
}
],
"should": [
{
"match": {
"sex": "男"
}
}
]
}
}
}
2.3.3.8、范围查询
range 查询找出那些落在指定区间内的数字或者时间。range 查询允许以下字符
操作符 | 说明 |
---|---|
gt | 大于> |
gte | 大于等于>= |
lt | 小于< |
lte | 小于等于<= |
在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search
{
"query": {
"range": {
"age": {
"gte": 30,
"lte": 35
}
}
}
}
2.3.3.9、模糊查询
返回包含与搜索字词相似的字词的文档。
编辑距离是将一个术语转换为另一个术语所需的一个字符更改的次数。这些更改可以包括:
-
更改字符(box → fox)
-
删除字符(black → lack)
-
插入字符(sic → sick)
-
转置两个相邻字符(act → cat)
为了找到相似的术语,fuzzy 查询会在指定的编辑距离内创建一组搜索词的所有可能的变体或扩展。然后查询返回每个扩展的完全匹配。通过 fuzziness 修改编辑距离。一般使用默认值 AUTO,根据术语的长度生成编辑距离。
在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search
{
"query": {
"fuzzy": {
"title": {
"value": "zhangsan"
}
}
}
}
{
"query": {
"fuzzy": {
"title": {
"value": "zhangsan",
"fuzziness": 2
}
}
}
}
2.3.3.10、单字段排序
sort 可以让我们按照不同的字段进行排序,并且通过 order 指定排序的方式。desc 降序,asc升序。在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search
{
"query": {
"match": {
"name": "zhangsan"
}
},
"sort": [
{
"age": {
"order": "desc"
}
}
]
}
2.3.3.11、多字段排序
假定我们想要结合使用 age 和 *score 进行查询,并且匹配的结果首先按照年龄排序,然后按照相关性得分排序在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/*search
{
"query": {
"match_all": {}
},
"sort": [
{
"age": {
"order": "desc"
}
},
{
"_score": {
"order": "desc"
}
}
]
}
2.3.3.12、高亮查询
在进行关键字搜索时,搜索出的内容中的关键字会显示不同的颜色,称之为高亮。Elasticsearch 可以对查询内容中的关键字部分,进行标签和样式(高亮)的设置。在使用 match 查询的同时,加上一个 highlight 属性:
-
pre_tags:前置标签
-
post_tags:后置标签
-
fields:需要高亮的字段
-
title:这里声明 title 字段需要高亮,后面可以为这个字段设置特有配置,也可以空
在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search
{
"query": {
"match": {
"name": "zhangsan"
}
},
"highlight": {
"pre_tags": "<font color='red'>",
"post_tags": "</font>",
"fields": {
"name": {}
}
}
}
响应结果
{
"took": 44,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 1.3862942,
"hits": [
{
"_index": "student",
"_type": "_doc",
"_id": "1001",
"_score": 1.3862942,
"_source": {
"name": "zhangsan",
"nickname": "zhangsan",
"sex": "男",
"age": 30
},
"highlight": {
"name": [
"<font color='red'>zhangsan</font>"
]
}
}
]
}
}
2.3.3.14、分页查询
-
from:当前页的起始索引,默认从 0 开始。 from = (pageNum - 1) * size
-
size:每页显示多少条
在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"age": {
"order": "desc"
}
}
],
"from": 0,
"size": 2
}
响应结果
{
"took": 5,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 5,
"relation": "eq"
},
"max_score": null,
"hits": [
{
"_index": "student",
"_type": "_doc",
"_id": "1004",
"_score": null,
"_source": {
"name": "zhangsan1",
"nickname": "zhangsan1",
"sex": "女",
"age": 50
},
"sort": [
50
]
},
{
"_index": "student",
"_type": "_doc",
"_id": "1003",
"_score": null,
"_source": {
"name": "wangwu",
"nickname": "wangwu",
"sex": "女",
"age": 40
},
"sort": [
40
]
}
]
}
}
2.3.3.15、聚合查询
聚合允许使用者对 es 文档进行统计分析,类似与关系型数据库中的 group by,当然还有很多其他的聚合,例如取最大值、平均值等等。
对某个字段取最大值 max
{
"aggs": {
"max_age": {
"max": {
"field": "age"
}
}
},
"size": 0
}
对某个字段取最小值 min
{
"aggs": {
"min_age": {
"min": {
"field": "age"
}
}
},
"size": 0
}
对某个字段求和 sum
{
"aggs": {
"sum_age": {
"sum": {
"field": "age"
}
}
},
"size": 0
}
对某个字段取平均值 avg
{
"aggs": {
"avg_age": {
"avg": {
"field": "age"
}
}
},
"size": 0
}
对某个字段的值进行去重之后再取总数
{
"aggs": {
"distinct_age": {
"cardinality": {
"field": "age"
}
}
},
"size": 0
}
State 聚合
stats 聚合,对某个字段一次性返回 count,max,min,avg 和 sum 五个指标
{
"aggs": {
"stats_age": {
"stats": {
"field": "age"
}
}
},
"size": 0
}
响应结果
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 5,
"relation": "eq"
},
"max_score": null,
"hits": []
},
"aggregations": {
"stats_age": {
"count": 5,
"min": 20.0,
"max": 50.0,
"avg": 34.0,
"sum": 170.0
}
}
}
2.3.3.16、桶聚合查询
桶聚和相当于 sql 中的 group by 语句
terms 聚合,分组统计
{
"aggs": {
"age_groupby": {
"terms": {
"field": "age"
}
}
},
"size": 0
}
在 terms 分组下再进行聚合
{
"aggs": {
"age_groupby": {
"terms": {
"field": "age"
}
}
},
"size": 0
}
3、单机和集群
3.1、单机
单台 Elasticsearch 服务器提供服务,往往都有最大的负载能力,超过这个阈值,服务器性能就会大大降低甚至不可用,所以生产环境中,一般都是运行在指定服务器集群中。除了负载能力,单点服务器也存在其他问题:
-
单台机器存储容量有限
-
单服务器容易出现单点故障,无法实现高可用
-
单服务的并发处理能力有限
配置服务器集群时,集群中节点数量没有限制,大于等于 2 个节点就可以看做是集群了。一般出于高性能及高可用方面来考虑集群中节点数量都是 3 个以上。
3.2、集群 Cluster
一个集群就是由一个或多个服务器节点组织在一起,共同持有整个的数据,并一起提供索引和搜索功能。一个 Elasticsearch 集群有一个唯一的名字标识,这个名字默认就是"elasticsearch"。这个名字是重要的,因为一个节点只能通过指定某个集群的名字,来加入这个集群。
3.3、节点 Node
集群中包含很多服务器,一个节点就是其中的一个服务器。作为集群的一部分,它存储数据,参与集群的索引和搜索功能。一个节点也是由一个名字来标识的,默认情况下,这个名字是一个随机的漫威漫画角色的名字,这个名字会在启动的时候赋予节点。这个名字对于管理工作来说挺重要的,因为在这个管理过程中,你会去确定网络中的哪些服务器对应于 Elasticsearch 集群中的哪些节点。一个节点可以通过配置集群名称的方式来加入一个指定的集群。默认情况下,每个节点都会被安排加入到一个叫做"elasticsearch"的集群中,这意味着,如果你在你的网络中启动了若干个节点,并假定它们能够相互发现彼此,它们将会自动地形成并加入到一个叫做"elasticsearch"的集群中
在一个集群里,只要你想,可以拥有任意多个节点。而且,如果当前你的网络中没有运行任何 Elasticsearch 节点,这时启动一个节点,会默认创建并加入一个叫做"elasticsearch"的集群。
3.4、Windows集群的搭建
创建 elasticsearch-cluster 文件夹,在内部复制三个 elasticsearch 服务

修改集群文件目录中每个节点的 config/elasticsearch.yml 配置文件
node1
#节点 1 的配置信息:
#集群名称,节点之间要保持一致
cluster.name: my-elasticsearch
#节点名称,集群内要唯一
node.name: node-1001
node.master: true
node.data: true
#ip 地址
network.host: localhost
#http 端口
http.port: 1001
#tcp 监听端口
transport.tcp.port: 9301
#discovery.seed_hosts: ["localhost:9301", "localhost:9302","localhost:9303"]
#discovery.zen.fd.ping_timeout: 1m
#discovery.zen.fd.ping_retries: 5
#集群内的可以被选为主节点的节点列表
#cluster.initial_master_nodes: ["node-1", "node-2","node-3"]
#跨域配置
#action.destructive_requires_name: true
http.cors.enabled: true
http.cors.allow-origin: "*"
node2
#节点 2 的配置信息:
#集群名称,节点之间要保持一致
cluster.name: my-elasticsearch
#节点名称,集群内要唯一
node.name: node-1002
node.master: true
node.data: true
#ip 地址
network.host: localhost
#http 端口
http.port: 1002
#tcp 监听端口
transport.tcp.port: 9302
discovery.seed_hosts: ["localhost:9301"]
discovery.zen.fd.ping_timeout: 1m
discovery.zen.fd.ping_retries: 5
#集群内的可以被选为主节点的节点列表
#cluster.initial_master_nodes: ["node-1", "node-2","node-3"]
#跨域配置
#action.destructive_requires_name: true
http.cors.enabled: true
http.cors.allow-origin: "*"
然后分别启动服务,查看集群状态 :http://localhost:9201/_cluster/health
{
"cluster_name": "elasticsearch",
"status": "green",
"timed_out": false,
"number_of_nodes": 3,
"number_of_data_nodes": 3,
"active_primary_shards": 2,
"active_shards": 4,
"relocating_shards": 0,
"initializing_shards": 0,
"unassigned_shards": 0,
"delayed_unassigned_shards": 0,
"number_of_pending_tasks": 0,
"number_of_in_flight_fetch": 0,
"task_max_waiting_in_queue_millis": 0,
"active_shards_percent_as_number": 100.0
}
其中Status字段指示当前集群在总体上否工作正常,它的三种颜色的含义如下:
-
green:所有主分片和副本分片都正常
-
yellow:所有的主分片都正常运行,但不是所有的副本分片都正常的运行
-
red:有主分片没有正常的运行
3.5、在Linux下安装elasticsearch
下载安装包:Elasticsearch 7.17.16 | Elastic,选择Linux,然后将下载完毕后的上传到Liunx虚拟机中解压:
tar -zxvf elasticsearch-7.17.16-linux-x86_64.tar.gz
创建用户
因为安全问题,Elasticsearch 不允许 root 用户直接运行,所以要创建新用户,在 root 用
户中创建新用户。
useradd es_root
passwd es_root
chwon -R es_root:es_root /software/elasticsearch
修改配置
修改/opt/module/es/config/elasticsearch.yml 文件
# 加入如下配置
cluster.name: elasticsearch
node.name: node-1
network.host: 0.0.0.0
http.port: 9200
cluster.initial_master_nodes: ["node-1"]
修改/etc/security/limits.conf
# 在文件末尾中增加下面内容
# 每个进程可以打开的文件数的限制
es soft nofile 65536
es hard nofile 65536
修改/etc/security/limits.d/20-nproc.conf
# 在文件末尾中增加下面内容
# 每个进程可以打开的文件数的限制
es soft nofile 65536
es hard nofile 65536
# 操作系统级别对每个用户创建的进程数的限制
* hard nproc 4096
# 注:* 带表 Linux 所有用户名称
修改/etc/sysctl.conf
# 在文件中增加下面内容
# 一个进程可以拥有的 VMA(虚拟内存区域)的数量,默认值为 65536
vm.max_map_count=655360
重新加载
sysctl -p
按说到这里起始已经可以启动了,但是这里有两个小问题要解决,jdk版本以及启动后一个报错的小问题,一般Liunx中都会有jdk,然后启动的时候就会导致报错,直接vim elasticsearch-7.4.0/bin/elasticsearch加配置
#=======添加配置解决jdk版本问题=====
export JAVA_HOME=/opt/elasticsearch-7.4.0/jdk # (将原目录修改为es中自带jdk的配置目录)
export PATH=$JAVA_HOME/bin:$PATH
#============
#=======添加配置解决jdk版本问题=====
if [ -x "$JAVA_HOME/bin/java" ]; then
JAVA="/opt/elasticsearch-7.4.0/jdk/bin/java"
else
JAVA=`which java`
fi
#============
然后就算是启动后爆出
AccessDeniedException optappseselasticsearchconfigelasticsearch.keystore
主要是因为es在启动后会生成这个文件,然后他的所属用户是root而是不是es_root,修改权限
cd /opt/apps/es/elasticsearch/config
chown -R es:esg elasticsearch.keystore
然后就是启动后,直接将虚拟机的内存直接沾满了,这可不太好!修改配置
vim /usr/local/elasticsearch-7.13.2/config/jvm.options
默认配置如下:
-Xms2g
-Xmx2g
默认的配置占用内存太多了,调小一些:
-Xms256m
-Xmx256m
为Elasticsearch设置登录密码
ES7.x以后的版本将安全认证功能免费开放了,并将X-pack插件集成了到了开源的ElasticSearch版本中。下面将介绍如何利用X-pack给ElasticSearch相关组件设置用户名和密码。
编辑配置文件
vim /usr/local/elasticsearch-7.13.2/config/elasticsearch.yml
xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true
重启后
/usr/local/elasticsearch-7.13.2/bin/elasticsearch-setup-passwords interactive
这里依次设置elastic、kibana、logstash等的访问密码
3.6、Linux 集群
这里的下载安装就不说了,主要是安装后的配置,
修改配置文件
修改/opt/module/es/config/elasticsearch.yml 文件,分发文件
# 加入如下配置
#集群名称
cluster.name: cluster-es
#节点名称,每个节点的名称不能重复
node.name: node-1
#ip 地址,每个节点的地址不能重复
network.host: linux1
#是不是有资格主节点
node.master: true
node.data: true
http.port: 9200
# head 插件需要这打开这两个配置
http.cors.allow-origin: "*"
http.cors.enabled: true
http.max_content_length: 200mb
#es7.x 之后新增的配置,初始化一个新的集群时需要此配置来选举 master
cluster.initial_master_nodes: ["node-1"]
#es7.x 之后新增的配置,节点发现
discovery.seed_hosts: ["linux1:9300","linux2:9300","linux3:9300"]
gateway.recover_after_nodes: 2
network.tcp.keep_alive: true
network.tcp.no_delay: true
transport.tcp.compress: true
#集群内同时启动的数据任务个数,默认是 2 个
cluster.routing.allocation.cluster_concurrent_rebalance: 16
#添加或删除节点及负载均衡时并发恢复的线程个数,默认 4 个
cluster.routing.allocation.node_concurrent_recoveries: 16
#初始化数据恢复时,并发恢复线程的个数,默认 4 个
cluster.routing.allocation.node_initial_primaries_recoveries: 16
修改/etc/security/limits.conf ,分发文件
# 在文件末尾中增加下面内容
es soft nofile 65536
es hard nofile 65536
修改/etc/security/limits.d/20-nproc.conf,分发文件
# 在文件末尾中增加下面内容
es soft nofile 65536
es hard nofile 65536
* hard nproc 4096
# 注:* 带表 Linux 所有用户名称
修改/etc/sysctl.conf
# 在文件中增加下面内容
vm.max_map_count=655360
重新加载
sysctl -p