ElasticSearch索引学习 作者:李帅
[TOC]
1.索引概念 2 索引基本操作
文档地址:https://www.elastic.co/guide/en/elasticsearch/reference/current/indices.html?baymax=rec&rogue=rec-1&elektra=guide
2.1 创建索引 Elasticsearch采用Rest风格API,因此其API就是一次http请求,你可以用任何工具发起http请求
请求分为 PUT
POST
GET
DELETE
GET
: 查询数据
POST
: 插入数据,也可以实现查询,查询条件复杂时,参数可以使用json
PUT
: 更新数据,实际上很多情况下 es 不是很清晰你到底要作什么,所有有时候添加也需要使用 PUT 请求,如果错了,会告诉我请求方式不对
DELETE
: 删除数据
2.1.1创建索引的请求格式
请求方式:PUT
请求路径:/索引库名
请求参数:json格式
索引的格式要求
**<index>
**(必需,字符串)要创建的索引的名称。
索引名称必须满足以下条件:
仅小写
不能包含\
, /
, *
, ?
, "
, <
, >
, |
,
(空格字符), ,
,#
7.0 之前的索引可以包含冒号 ( :
),但它已被弃用并且在 7.0+ 中不受支持
不能以-
, _
,开头+
不能是.
或..
不能超过 255 个字节(注意它是字节,因此多字节字符将更快地计入 255 个限制)
.
不推荐使用以 开头的名称,插件管理的隐藏索引 和内部索引 除外
mappings
(可选,映射对象 )索引中字段的映射。如果指定,此映射可以包括:
请参阅映射 。
settings
(可选,索引设置对象 )索引的 配置选项。请参阅索引设置 。
其他略
2.1.2 创建索引的请求Demo 直接创建索引
执行结果如下:
1 2 3 4 5 { "acknowledged" : true, # 表示是否在集群中成功创建索引 "shards_acknowledged" : true, # 表示是否在超时之前为索引中的每个分片启动了所需数量的分片副本 "index" : "ls_person" # 索引的日志 }
出现如下,表示索引创建成功了
创建索引时设置settings
1 2 3 4 5 6 7 8 9 10 # 创建索引时添加setting 设置 PUT /ls_person_two { "settings" : { "index": { # index 可以不写 "number_of_replicas": 1, # 默认的备份数,也是 1 "number_of_shards": 1 # 分片数默认为1 } } }
创建索引时指定索引的结构mapping
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #创建索引的映射 PUT /ls_person_three?pretty { "settings" : { "number_of_shards" : 1 }, "mappings" : { "properties" : { "name" : { "type" : "text" }, "age" :{ "type" : "integer" }, "birthday" :{ "type" : "date" , "format" : ["yyyy-MM-dd" ] } } } }
在kibana中查看结构如下:
**创建索引时允许提供别名
**
2.1.3 创建索引的Java代码演示 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public class ESCreateIndexDemo { private static final Logger logger = Logger.getLogger(ESCreateIndexDemo.class); public static final String index = "ls_person_five811" ; @Test public void testCreateIndex () throws IOException { HttpHost httpHost = new HttpHost("192.168.154.129" , 9200 ); RestClientBuilder restClientBuilder = RestClient.builder(httpHost); RestHighLevelClient client = new RestHighLevelClient(restClientBuilder); CreateIndexRequest createIndexRequest = new CreateIndexRequest(index); CreateIndexResponse response = client.indices().create(createIndexRequest, RequestOptions.DEFAULT); logger.debug("创建结果:" + response.isAcknowledged()); }
2.2 删除索引 删除索引使用DELETE
请求
语法
注意
删除索引会删除其文档
、分片
和元数据
<index>
(必需,字符串)要删除的索引的逗号分隔列表。
要删除所有索引,请使用_all
或*
。要禁止删除带有_all
或 通配符表达式的索引,请将 action.destructive_requires_name
集群设置设置为true
。
设置为true
时,表示您必须指定索引名称才能删除索引 。无法_all
使用通配符删除所有索引。
2.2.1 删除索引的请求Demo 如果要删除多个索引,中间使用都好隔开
1 DELETE /ls_person_three,ls_person_five,ls_person_three
如下图,可以看到刚才创建的索引已经删除了
2.2.2 删除索引通过Java代码方式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @Test public void deleteIndexTest () throws IOException { HttpHost httpHost = new HttpHost("192.168.154.129" , 9200 ); RestClientBuilder restClientBuilder = RestClient.builder(httpHost); RestHighLevelClient client = new RestHighLevelClient(restClientBuilder); DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("ls_person" , "person" ); AcknowledgedResponse response = client.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT); logger.info("执行结果:" + response.isAcknowledged()); }
删除后在控制台查看如下:
由此,可以看到,索引已经删除成功了
2.3 获取索引 Get
请求可以帮我们查看索引信息
支持查询多个,索引
和别名
的逗号分隔列表。支持通配符 *
或_all
。
2.3.1 获取索引的请求Demo 1 2 3 4 5 6 7 8 9 10 11 # 获取单个索引 GET ls_person1 # 获取多个索引,中间使用逗号隔开 GET ls_person1,ls_person2 #使用通配符获取索引 GET user* # 获取全部索引 GET _all
2.3.2 获取索引的代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 @Test public void getIndexTest () throws IOException { HttpHost httpHost = new HttpHost("192.168.154.129" , 9200 ); RestClientBuilder restClientBuilder = RestClient.builder(httpHost); RestHighLevelClient client = new RestHighLevelClient(restClientBuilder); GetIndexRequest getIndexRequest = new GetIndexRequest("ls_person1" ,"ls_person2" ); GetIndexResponse response = client.indices().get(getIndexRequest, RequestOptions.DEFAULT); String[] indices = response.getIndices(); for (String indexName : indices) { logger.info("查询出的索引名称:" + indexName); } }
2.4 检查索引是否存在 检查数据
、索引
或别名
是否存在。多个之间使用逗号隔开
2.4.1 检查索引是否存在的请求Demo 1 2 # 检查索引是否存在 HEAD ls_person1
返回值为200
表示存在 404
表示不存在,返回值格式不一样 如下所示:
1 2 200 - OK # 存在 {"statusCode":404,"error":"Not Found","message":"404 - Not Found"} # 不存在,如果是多个索引,有一个不存在,结果就是404
2.4.2 检查索引是否存在的请求JAVA实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Test public void checkIndexExist () throws IOException { HttpHost httpHost = new HttpHost("192.168.154.129" , 9200 ); RestClientBuilder restClientBuilder = RestClient.builder(httpHost); RestHighLevelClient client = new RestHighLevelClient(restClientBuilder); GetIndexRequest getIndexRequest = new GetIndexRequest("ls_person1" , "ls_person1" ); boolean exists = client.indices().exists(getIndexRequest, RequestOptions.DEFAULT); logger.info("索引是否存在结果:" + exists); }
2.5 关闭索引 API
:
作用:不允许被关闭的索引进行任何的查询或者写入操作。无法索引文档或在封闭索引中搜索文档。这允许封闭索引不必维护用于索引或搜索文档的内部数据结构,从而减少集群上的开销。
1 POST / my-index-000001 / _close
封闭索引会消耗大量磁盘空间,这可能会导致托管环境出现问题。关闭索引可以通过集群设置 API 设置cluster.indices.close.enable
为来禁用false
。默认值为true
.
2.6 打开索引 1 POST / my-index-000001 / _open
关闭索引被阻止进行读/写操作,并且不允许打开索引允许的所有操作。无法索引文档或在封闭索引中搜索文档。这允许封闭索引不必维护用于索引或搜索文档的内部数据结构,从而减少集群上的开销。
在打开或关闭索引时,master 负责重新启动索引分片以反映索引的新状态。然后分片将经历正常的恢复过程。打开/关闭索引的数据由集群自动复制,以确保始终安全地保留足够的分片副本。
2.7 其他操作 关于索引官网上还有一些其他操作,有兴趣的可以自行查看索引的API
API地址如下:https://www.elastic.co/guide/en/elasticsearch/reference/current/indices.html?baymax=rec&rogue=rec-1&elektra=guide
3 索引字段映射 3.1 创建索引时指定字段映射 3.1.1 创建索引映射Demo 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #创建索引的映射 PUT /ls_person?pretty { "settings" : { "number_of_shards" : 1 }, "mappings" : { "properties" : { "name" : { "type" : "text" }, "age" :{ "type" : "integer" }, "birthday" :{ "type" : "date" , "format" : ["yyyy-MM-dd" ] } } } }
3.1.2 创建索引映射Demo的Java实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 @Test public void createIndexAndMapping() throws IOException { HttpHost httpHost = new HttpHost("192.168.154.129", 9200); RestClientBuilder restClientBuilder = RestClient.builder(httpHost); RestHighLevelClient client = new RestHighLevelClient(restClientBuilder); Settings.Builder settings = Settings.builder().put("number_of_shards",1); XContentBuilder xContentBuilder = JsonXContent.contentBuilder() .startObject() .startObject("properties") .startObject("name") .field("type", "text") .endObject() .startObject("age") .field("type", "integer") .endObject() .startObject("birthday") .field("type", "date") .field("format", "yyyy-MM-dd") .endObject() .endObject() .endObject(); CreateIndexRequest createIndexRequest = new CreateIndexRequest("ls_person_mapping"); createIndexRequest.settings(settings) .mapping(xContentBuilder); CreateIndexResponse response = client.indices().create(createIndexRequest, RequestOptions.DEFAULT); logger.info("索引创建结果:" + response.isAcknowledged()); }
kibana运行截图如下:
由此,可见,索引的映射创建成功了
3.2 获取索引字段映射 3.2.1 获取索引映射请求 语法
获取一个
或者多个
索引的映射信息
1 2 3 4 5 6 7 8 9 10 GET /<target>/_mapping GET /索引名称(多个之间使用逗号隔开)/_mapping # 获取多个索引,中间使用逗号隔开 GET /ls_person,ls_person20/_mapping # 所有的索引映射 GET /*/_mapping # 所有的索引映射 GET /_all/_mapping # 所有的索引映射 GET /_mapping
<target>
(可选,字符串)用于限制请求的数据流
、索引
和别名
的逗号分隔列表。支持通配符 *
或_all
。
执行结果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 { "ls_person20" : { "mappings" : { "properties" : { "age" : { "type" : "integer" }, "birthday" : { "type" : "date" , "format" : "[yyyy-MM-dd]" }, "name" : { "type" : "text" } } } }, "ls_person" : { "mappings" : { "properties" : { "age" : { "type" : "integer" }, "birthday" : { "type" : "date" , "format" : "[yyyy-MM-dd]" }, "name" : { "type" : "text" } } } } }
3.2.2 获取索引映射Java代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Test public void getIndexMappingTest () throws IOException { HttpHost httpHost = new HttpHost("192.168.154.129" , 9200 ); RestClientBuilder restClientBuilder = RestClient.builder(httpHost); RestHighLevelClient client = new RestHighLevelClient(restClientBuilder); GetIndexRequest getIndexRequest = new GetIndexRequest("ls_person_mapping" ); GetIndexResponse response = client.indices().get(getIndexRequest, RequestOptions.DEFAULT); String indexName = "ls_person_mapping" ; MappingMetadata metaData = response.getMappings().get(indexName); logger.info("索引名称:" + indexName); logger.info("索引映射数据" + metaData.getSourceAsMap()); }
执行结果如下:
1 2 索引名称:ls_person_mapping 索引映射数据{properties={birthday={format=yyyy-MM-dd, type=date}, name={type=text}, age={type=integer}}}
3.3 获取索引Mappping字段映射 3.3.1 获取索引Mapping的字段映射Demo 定义
检索一个或多个字段的映射定义 。对于数据流,API 检索流的支持索引的字段映射。
语法
1 2 3 4 5 6 7 GET /_mapping/field/<field> GET /<target>/_mapping/field/<field> <target> (可选,字符串)用于限制请求的数据流、索引和别名的逗号分隔列表。支持通配符 ( *)。要定位所有数据流和索引,请省略此参数或使用*或_all。 <field> (可选,字符串)用于限制返回信息的字段的逗号分隔列表或通配符表达式
例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 PUT /publications?pretty { "mappings" : { "properties" : { "id" : { "type" : "text" }, "title" : { "type" : "text" }, "abstract" : { "type" : "text" }, "author" : { "properties" : { "id" : { "type" : "text" }, "name" : { "type" : "text" } } } } } } #获取索引Mapping的字段映射 GET ls_person20/_mapping/field/birthday # get mapping API 允许您指定以逗号分隔的字段列表。 GET /publications/_mapping/field/author.id,abstract,name?pretty # 使用通配符形式的字段映射 GET publications/_mapping/field/a* # 上述<target>和<field>请求路径参数都支持逗号分隔的列表和通配符表达式。 这里的ls_person是我上文中创建的索引对象 GET ls_person,ls_person20/_mapping/field/name,birthday
3.3.2 获取索引Mapping的字段映射Java实现 3.4 更新索引Mapping映射 定义
:向现有数据流或索引添加新字段
语法
:
1 2 3 PUT /<target>/_mapping <target> (必需,字符串)用于限制请求的数据流、索引和别名的逗号分隔列表。支持通配符 ( *)。要定位所有数据流和索引,请省略此参数或使用*或_all。
3.4.1 更新索引Mapping映射DEMO 单个索引属性更新
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # 创建索引 PUT /ls_person30 # 更新索引字段映射 PUT /ls_person30/_mapping { "properties" :{ "name" :{ "type" :"keyword" }, "age" :{ "type" : "integer" } } }
多个索引更新
更新映射 API 可以通过单个请求应用于多个索引
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 # Create the two indices PUT /ls_person40 PUT /ls_person41 # Update both mappings PUT /ls_person40,ls_person41/_mapping { "properties" : { "user" : { "properties" : { "name" : { "type" : "keyword" } } } } } GET ls_person40,ls_person41/_mapping
向现有的字段对象中添加新的属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 PUT /ls_person50?pretty { "mappings": { "properties": { "name": { "properties": { "first": { "type": "text" } } } } } } get ls_person50 # 向name字段中添加新的字段last PUT /ls_person50/_mapping?pretty { "properties": { "name": { "properties": { "last": { "type": "text" } } } } }
将多字段添加到现有字段中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 PUT /ls_person60?pretty { "mappings" : { "properties" : { "city" : { "type" : "text" } } } } get ls_person60 PUT /ls_person60/_mapping?pretty { "properties" : { "city" : { "type" : "text" , "fields" : { "raw" : { "type" : "keyword" } } } } }
3.4.2 更新索引Mapping映射Java实现 略
3.5 检查索引类型是否存在
ElasticSearch7.0 之后,索引类型就已经弃用了
https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-types-exists.html
3.6 索引使用情况的API
https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-disk-usage.html
定义
:分析索引或数据流的每个字段的磁盘使用情况
语法
: 有一些可选参数。实际测试没有得到我想要的结果,有兴趣的同学可以在上面的官网中查看和学习
1 POST /<target>/_disk_usage
4.索引设置 4.1 获取索引设置 作用
: 返回一个或多个索引的设置信息.
格式
1 2 3 GET /<target>/_settings GET /<target>/_settings/<setting>
要获取集群中所有索引的设置.可以使用_all
或*
for <target>
。还支持通配符表达式
例如:
1 2 3 4 # 中间不要有空格,否则会提示 illegal_argument_exception request [GET /ls_person50,ls_person40] does not support having a body GET /ls_person50,ls_person40/_settings GET /_all/_settings GET /ls_person*/_settings
4.2 索引分析文本
https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-analyze.html
作用
:对文本字符串执行分析 并返回结果标记。
格式
:
1 2 3 4 5 6 7 GET /_analyze POST /_analyze GET /<index>/_analyze POST /<index>/_analyze
执行例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 # 索引分析操作 standard如果没有指定,分析器是默认的分析器。 GET /_analyze?pretty { "analyzer" : "standard" , "text" : "小河流水哗啦啦" } # 采用ik分词器的分词 需要自行安装 GET /_analyze { "analyzer" : "ik_max_word" , "text" : "小河流水哗啦啦" } # 文本字符串数组则将其作为多值字段进行分析 GET /ls_person/_analyze { "analyzer" : "ik_max_word" , "text" : [ "小河流水哗啦啦" , "我和姐姐去彩花t" ] }
analyzer
应用于提供的text
. 这可以是内置的分析器 ,也可以是 在索引中配置的分析器。
如果未指定此参数,则分析 API 使用字段映射中定义的分析器。如果未指定字段,则分析 API 使用索引的默认分析器。
如果未指定索引,或者索引没有默认分析器,则分析 API 使用标准分析器 standard
。
4.3 IK分词器安装 Lucene的IK分词器的很早就不维护了,索引现在我们要使用的是在其基础上维护升级的版本。因为我所使用的ElasticSearch
是7.12.0
版本,所以我的IK分词器也下载对应的7.12.0
的版本
IK分词器安装地址:https://github.com/medcl/elasticsearch-analysis-ik/releases/tag/v7.12.0
ik分词器,解压在elasticsearch
的plugin
目录下面。然后重新启动elasticsearch就可以使用了
例如:
1 /usr/local/software/elasticsearch-7.12.0/plugins
4.4 更新索引设置 作用
: 实时更改动态索引设置 。
执行例子
1 2 3 4 5 6 PUT /ls_person/_settings?pretty { "index" : { "number_of_replicas" : 3 } }
6.索引的别名管理 略
有兴趣的同学自行查看ES的API
7. 索引模板 有兴趣的同学自行查看ES的API
8. 索引监控 8.1 索引统计 定义
: 获取一个或多个数据流和索引的高级聚合和统计信息。
格式
1 2 3 4 5 GET /<target>/_stats/<index-metric> GET /<target>/_stats GET /_stats
默认情况下,返回的统计信息是索引级别的primaries
和total
聚合。 primaries
是仅主分片的值。 total
是主分片和副本分片的累计值。
要获取分片级别的统计信息,请将level
参数设置为shards
。
执行例子
1 2 3 4 5 6 7 # 获取多个索引的统计信息 多个之间使用逗号隔开 GET /ls_person,ls_person2/_stats # 获取集群中所有的索引的统计信息 GET /_stats GET /_stats/merge,refresh?pretty GET /ls_person30/_stats/merge,refresh?pretty
8.2 索引字段统计 定义
: 返回索引的每个分片和字段的字段使用信息。当查询在集群上运行时,会自动捕获字段使用统计信息。访问给定字段的分片级搜索请求,即使在该请求期间多次,也计为一次使用。
格式
1 GET /<index>/_field_usage_stats
执行例子
略。未来版本
该功能可能会删除。官网提供的查询例子貌似有问题
8.3 索引分片存储 略
定义
: 一个或多个索引中检索有关副本分片的存储信息
格式
:
1 2 3 GET /<target>/_shard_stores GET /_shard_stores
8.4 索引恢复 略
定义
:返回有关一个或多个索引的正在进行和已完成的分片恢复的信息
格式
:
1 2 3 GET /<target>/_recovery GET /_recovery
9.索引状态管理 9.1 清除索引的缓存 定义
:清除一个或多个索引的缓存
格式
:
1 2 3 POST /<target>/_cache/clear POST /_cache/clear
支持通配符 ( *
)。要定位所有数据流和索引,请省略此参数或使用*
或_all
。
清除特定缓存
默认情况下,清除缓存 API 会清除所有缓存。您可以通过将以下查询参数设置为来仅清除特定缓存true
1 2 3 4 5 6 7 8 9 10 11 # 清除特定缓存 # 仅清除字段缓存 POST /ls_person/_cache/clear?fielddata=true&pretty # 只清除查询缓存 POST /ls_person/_cache/clear?query=true&pretty # 只清除请求缓存 POST /ls_person/_cache/clear?request=true&pretty # 不指定索引清除所有的缓存 POST /_cache/clear?pretty # 清除多个索引的缓存 多个之间使用逗号隔开 POST /ls_person,ls_person2/_cache/clear?pretty
9.2 索引刷新
近实时搜索:https://www.elastic.co/guide/en/elasticsearch/reference/current/near-real-time.html
定义
: 对一个或者多个索引进行刷新操作。可用于搜索
使用刷新 API 显式地使自上次刷新以来对一个
或多个索引
执行的所有操作可用于搜索。
默认情况下,Elasticsearch 每秒
都会定期刷新索引,但仅限于在过去 30 秒内收到一个或多个搜索请求的索引。
您可以使用index.refresh_interval
设置更改此默认间隔。
刷新请求是同步
的,在刷新操作完成之前不会返回响应。
格式
:
1 2 3 4 5 6 7 POST <target>/_refresh GET <target>/_refresh POST /_refresh GET /_refresh
使用例子
1 2 3 4 5 6 # 刷新一个或者多个索引 POST /ls_person,ls_person2/_refresh?pretty # 刷新所有的索引 POST /_refresh
注意
刷新是资源密集型的。为了确保良好的集群性能,我们建议尽可能等待 Elasticsearch 的定期刷新
,而不是执行显式刷新。
9.3 刷新 定义
: 刷新一个或多个索引
刷新数据流
或索引是确保当前仅存储在事务日志 中的任何数据也永久存储
在 Lucene 索引中的过程。
重新启动时,Elasticsearch 会将所有未刷新的操作从事务日志中重放到 Lucene 索引中,以将其恢复到重新启动前的状态。Elasticsearch 会根据需要自动触发刷新.
一旦每个操作被刷新,它就会永久存储在 Lucene 索引中。这可能意味着不需要在事务日志中维护它的额外副本,除非它因某些其他原因被保留 。事务日志由多个文件组成,称为generation
,一旦不再需要,Elasticsearch 将删除任何生成文件,从而释放磁盘空间。
格式
:
1 2 3 4 5 6 7 POST /<target>/_flush GET /<target>/_flush POST /_flush GET /_flush
使用例子
1 2 3 4 5 # 刷新特定索引或者数据。支持多个,中间使用逗号隔开 POST /ls_person,ls_person2/_flush?pretty # 刷新所有的索引和数据流 POST /_flush
9.4 强制合并 一个或多个索引的分片 略