Elasticsearch - 使用REST API操作Elasticsearch教程(附:curl、ES SQL样例)
Elasticsearch 是一个强大的开源搜索和分析引擎,它通过 RESTful API 提供了灵活而直观的方式来与其进行交互。本文通过样例演示如何使用 REST API 操作 Elasticsearch。
(2)下面命令创建一个具有 3 个分片的索引库:
(3)此时再查看这个索引库的数据就查询不到了,会提示这个索引库已经被 close 掉了。
(2)索引库 open 之后就可以查询了:
(2)在添加索引时,如果没有指定数据的 ID,则 Elasticsearch 会自动生成一个随机的唯一 ID:
(2)查询时可以指定只获取部分字段的内容:
(3)查询指定索引库中的所有数据。
提示:本文我使用 CURL 工具来调用 Elasticsearch 的 REST API。CURL 是利用 URL 语法在命令行下工作的开源文件传输工具。使用 CURL 工具可以方便地实现常见的 GET/POST 请求。 在 CURL 后面,通过 -X 参数指定请求类型,通过 -d 指定要传递的参数。
一、索引库的操作
1,创建索引库
(1)比如下面命令创建一个名为 test 的索引库:
注意:索引库名称必须全部小写,不能以 _、-、+ 开头,也不能包含特殊符号。
curl -XPUT 'http://node1:9200/test/'

(2)下面命令创建一个具有 3 个分片的索引库:
索引库可以提前创建,也可以在后期添加数据时直接指定一个不存在的素引库(Elasticsearch 默认会自动创建这个索引库)。手工创建索引库和自动创建索引库的区别是:
- 手工创建可以自定义索引库的配置信息(例如:索引库的分片数量)
- 自动创建则不可以
curl -XPUT "http://node1:9200/test/" -H 'Content-Type: application/json' -d '{ "settings": { "number_of_shards": 3 } }'
- 索引分片编号是从 0 开始的,并且索引分片在物理层面是存在的。由于我的 Elasticsearch 只有一个节点,使用 Cerebro 这个工具可以看到 test 素引库的 0 号、1 号、3 号分片都在同一个节点上。并且没有可用的副本。
提示:实线的框表示主分片,虚线的框表示副本分片。

- 到 Elasticsearch 节点中查看一下,Elasticsearch 中的所有数据都在 Elasticsearch 的数据存储目录下,默认是在 ES_HOME 下的 data 目录下。可以看到三个分片的文件夹:
提示:hVR_Ds7iSuKJrK3MmYWpdg 表示索引库的 UUID。

(3)在创建索引库的的时候还可以指定副本数量,比如下面命令创建一个具有 3 个分片和 1 个副本的索引库:
curl -XPUT "http://node1:9200/test2/" -H 'Content-Type: application/json' -d '{ "settings": { "number_of_shards": 3, "number_of_replicas": 1 } }'
- 分片数量只能在一开始创建索引库的时候指定,后期不能修改。副本数量可以随时修改。下面我们将刚才创建的索引的副本数量修改为 0。
curl -XPUT "http://node1:9200/test2/_settings" -H 'Content-Type: application/json' -d '{ "index": { "number_of_replicas": 0 } }'
2,删除索引库
下面命令删除 test 这个索引库:
curl -XDELETE 'http://node1:9200/test/'
3,关闭索引库
(1)假设 ES 已经收集了一段时间的日志数据,每一星期都会创建一个索引库,所以目前创建了 4 个索引库:
curl -H "Content-Type: application/json" -XPUT 'http://192.168.121.128:9200/log_20260301/' curl -H "Content-Type: application/json" -XPUT 'http://192.168.121.128:9200/log_20260308/' curl -H "Content-Type: application/json" -XPUT 'http://192.168.121.128:9200/log_20260315/' curl -H "Content-Type: application/json" -XPUT 'http://192.168.121.128:9200/log_20260322/'
- 然后分别向每个索引库里面初始化 1 条测试数据:
curl -H "Content-Type: application/json" -XPOST 'http://192.168.121.128:9200/log_20260301/_doc/1' -d'{"log":"info->20260301"}' curl -H "Content-Type: application/json" -XPOST 'http://192.168.121.128:9200/log_20260308/_doc/1' -d'{"log":"info->20260308"}' curl -H "Content-Type: application/json" -XPOST 'http://192.168.121.128:9200/log_20260315/_doc/1' -d'{"log":"info->20260315"}' curl -H "Content-Type: application/json" -XPOST 'http://192.168.121.128:9200/log_20260322/_doc/1' -d'{"log":"info->20260322"}'
(2)针对 3 个月以前的索引基本上就很少再使用了,为了减少对 ES 服务器的性能损耗(主要是内存的损耗),我们需要把这些长时间不使用的索引库 close 掉。比如下面命令将 log_20260301 索引库 close 掉:
注意:
- close 之后这个索引库里面的索引数据就不支持读写操作了,close 并不会删除索引库里面的数据,后期想要重新读写这个索引库里面的数据的话,可以通过 open 把索引库打开。
- 索引库 close 掉之后,虽然对 ES 服务器没有性能损耗了,但是对 ES 集群的磁盘占用还是存在的,所以可以根据需求,将一年以前的索引库彻底删除掉。
curl -XPOST 'http://192.168.121.128:9200/log_20260301/_close'
(3)此时再查看这个索引库的数据就查询不到了,会提示这个索引库已经被 close 掉了。
注意:这些 close 之后的索引库如果有设置别名,还行需要从索引库别名中移除掉,否则会导致无法使用从索引库别名查询数据,因为这个索引库别名中映射的有已经 close 掉的索引库。
curl -XGET 'http://192.168.121.128:9200/log_20260301/_search?pretty'

3,打开索引库
(1)执行下面命令将 log_20260301 索引库重新 open(打开)。curl -XPOST 'http://192.168.121.128:9200/log_20260301/_open'
(2)索引库 open 之后就可以查询了:
curl -XGET 'http://192.168.121.128:9200/log_20260301/_search?pretty'

二、索引的操作
1,添加索引
(1)下面命令在 test 索引库中添加一条 id 为 1 的索引,该索引对应的索引数据为 {"name":"hangge","age":20}
注意:
- 如果指定的索引库不存在,在使用时 Elasticsearch 会自动创建,只不过索引库分片数量默认是 1。
- 为了兼客之前的 API,Elasticsearch 现在取消了 Type,但是 API 中 Type 的位置还是预留出来了,官方建议统一使用“_doc”。
curl -XPOST "http://node1:9200/test/_doc/1" -H 'Content-Type: application/json' -d '{"name":"hangge","age":20}'

(2)在添加索引时,如果没有指定数据的 ID,则 Elasticsearch 会自动生成一个随机的唯一 ID:
curl -XPOST "http://node1:9200/test/_doc" -H 'Content-Type: application/json' -d '{"name":"baidu","age":99}'

2,查询索引
(1)下面命令查看 id=1 的索引数据:
curl -XGET 'http://node1:9200/test/_doc/1?pretty'

(2)查询时可以指定只获取部分字段的内容:
curl -XGET 'http://node1:9200/test/_doc/1?_source=name&pretty'

- 如果获取多个字段,使用逗号隔开:
curl -XGET 'http://node1:9200/test/_doc/1?_source=name,age&pretty'
(3)查询指定索引库中的所有数据。
curl -XGET 'http://node1:9200/test/_search?pretty'

(4)query 查询。下面命令根据 name 字段进行分词查询:
(2)局部更新则可以添加新字段或者更新已有字段。下面命令将 age 字段的值更新成 100:
(2)返回结果如下:
(2)数据格式说明:
(2)接着执行如下命令,调用 Bulk API 进行批量操作:
(3)最后查询下结果:
(2)下面是使用 like 语句进行模糊查询:
curl -H "Content-Type: application/json" \ -XGET "http://192.168.121.128:9200/test/_search?pretty" \ -d '{ "query": { "match": { "name": "航" } } }'

3,更新索引
(1)更新索引可以分为全部更新和局部更新。全部更新同添加索引。如果指定 ID 的索引数据(文档)已经存在,则执行更新操作。
提示:在执行更新操作时,Elasticsearch 首先将旧的文标识为删除状态,然后添加新的文档。旧的文档不会立即消失,但是你也无法访问,Elasticsearch 会在你继续添加更多文档时在后台清理掉已经被标识为删除状态的文档。
(2)局部更新则可以添加新字段或者更新已有字段。下面命令将 age 字段的值更新成 100:
curl -XPOST "http://node1:9200/test/_update/1" -H 'Content-Type: application/json' -d '{ "doc": { "age": 100 } }'
4,删除索引
(1)下面命令删除 id=1 的索引数据:
注意:删除一条索引数据(文档)也不会立即生效,它只是被标识成“删除”状态。Elasticsearch 会在之后用户添加更多索引数据时,才会在后台清理掉被标识为“删除”状态的数据。
curl -XDELETE "http://node1:9200/test/_doc/1"
(2)返回结果如下:
- 如果索引数据(文档)存在,则在 Elasticsearch 返回的结果中,result 属性的值为 deleted,_version(版本)属性的值 +1。
- 如果索引数据不存在,则在 Elasticsearch 返回的结果中,result 属性的值为 not_found,但是 _version 属性的值依然会 +1。这属于 Elasticsearch 的版本控制系统,它保证了我们在集群中多个节点之间的不同操作都被按照顺序正确标识了。
- 对于索引数据的每次写操作,无论是 index、update 还是 delete,Elasticsearch 都会将 _version 增加 1。该增加操作是原子的,并且保证在操作成功返回时会发生。

三、Bulk 批量操作
1,基本介绍
(1)Bulk API 可以帮助我们同时执行多个请求,提高效率。数据格式如下:
{ action: { metadata }} { request body }
- action:index/create/update/delete
- metadata:_index,_type,_id
- request body:_source(删除操作不需要)
create 和 index 的区别:如果数据存在,使用 create 操作失败,会提示文档已经存在,使用 index 则可以成功执行。
2,Bulk 一次最大可以处理多少数据量?
(1)Bulk 会把将要处理的数据加载到内存中,所以数据量是有限制的,最佳的数据量不是一个确定的数值,它取决于集群硬件,文档大小、文档复杂性,索引以及 ES 集群的负载。
- 一般建议是 1000-5000 个文档,如果文档很大,可以适当减少,文档总大小建议是 5-15MB,默认不能超过 100M。
(2)如果想要修改最大限制大小,可以在 ES 的配置文件中修改 http.max_content_length: 100mb,但是不建议,因为太大的话 Bulk 操作也会慢。
3,使用样例
(1)假设在 MySQL 中有一批数据,首先需要从 MySQL 中把数据读取出来,然后将数据转化为 Bulk 需要的数据格式。在这直接手工生成 Bulk 需要的数据格式,我们执行如下命令创建一个 request.json 文件:vi request.json
- 文件内容如下:
{ "index" : { "_index" : "test", "_id" : "1" } } { "field1" : "value1" } { "index" : { "_index" : "test", "_id" : "2" } } { "field1" : "value1" } { "delete" : { "_index" : "test", "_id" : "2" } } { "create" : { "_index" : "test", "_id" : "3" } } { "field1" : "value1" } { "update" : {"_index" : "test", "_id" : "1" } } { "doc" : {"field2" : "value2"} }
(2)接着执行如下命令,调用 Bulk API 进行批量操作:
curl -XPOST "http://localhost:9200/test/_bulk" -H "content-type:application/json" --data-binary @request.json
(3)最后查询下结果:
curl -XGET 'http://node1:9200/test/_search?pretty'

四、使用 Elasticsearch SQL
1,基本介绍
对于 Elasticsearch 中的结构化数据,使用 SQL 实现聚合统计会很方便,可以减少很多工作量。Elasticsearch SQL 支持常见的 SQL 语法,包括分组、排序、函数等,但是目前不支持 JOIN 操作。
2,使用样例
(1)下面是一个带条件和排序的查询:
curl -XPOST "http://node1:9200/_sql?format=txt" -H 'Content-Type: application/json' -d '{ "query":"select * from emp where age < 60 order by age desc limit 3" }'

(2)下面是使用 like 语句进行模糊查询:
curl -XPOST "http://node1:9200/_sql?format=txt" -H 'Content-Type: application/json' -d "{ \"query\": \"select * from emp where name like '方%'\" }"

(3)想要实现分词查询,我们可以使用 match。
(2)进入命令行后直接执行 SQL 命令即可:
curl -XPOST "http://node1:9200/_sql?format=txt" -H 'Content-Type: application/json' -d "{ \"query\": \"select * from emp where match(name, '方同')\" }"

3,在 SQL 命令行中操作 Elasticsearch SQL
(1)Elasticsearch SQL 出了支持 RESTAPI,还支持 SQL 命令行、JDBC\ODBC 等方式操作。以 SQL 命令行为例,首先执行如下命令进入命令行:
bin/elasticsearch-sql-cli
(2)进入命令行后直接执行 SQL 命令即可:
select * from emp where age < 50 or name = 'baidu' order by age desc limit 3;
