3、ES基础操作:RESTful API简介、索引的CRUD、文档的CRUD、批量操作(Bulk API)

好,咱们正式开始动手操作 Elasticsearch 了。

说实话,很多新手一上来就被各种概念搞晕了。什么分片、副本、倒排索引…… 我个人的建议是:先别管那么多,先学会怎么跟 ES “对话”。

ES 的对话方式,就是 RESTful API。说白了,就是发 HTTP 请求。

3.1 RESTful API 简介

RESTful API 不是什么高深的东西。你可以把它理解成一种“约定”。

我用一个比喻来解释:你想去图书馆借书。

  • GET:查询书的信息(查)
  • POST:新增一本书(增)
  • PUT:替换一本书(改,全量更新)
  • DELETE:删除一本书(删)

ES 的 API 地址长这样:

http://localhost:9200/{索引}/{类型}/{文档ID}

嗯,这里要注意一下。ES 7.0 之后,类型(Type)这个概念已经被废弃了。现在你写 API 的时候,类型统一用 _doc 占位就行。

我刚开始用 ES 6.x 的时候,还纠结过类型怎么设计。后来 7.x 一出来,直接一刀切了。所以,别在类型上花心思了。

3.2 索引的 CRUD

索引,你可以把它想象成 MySQL 里的“数据库”。

3.2.1 创建索引

创建一个名为 user 的索引:

PUT /user
{
  "settings": {
    "number_of_shards": 3,
    "number_of_replicas": 1
  }
}
我的经验: 分片数一旦设定,就不能改了(除非重建索引)。我建议你根据数据量预估一下。比如日志类数据,分片数可以设大一点;业务类数据,3-5个分片通常够用。

3.2.2 查询索引

查看索引信息:

GET /user

查看所有索引:

GET /_cat/indices?v

为什么加 ?v?因为 _cat 接口默认不显示表头,加上 v 就能看到列名了。这个小细节,我当年可是踩过坑的。

3.2.3 删除索引

DELETE /user
警告: 删除索引会直接删除所有数据,没有回收站!我曾经在测试环境执行过 DELETE /user*,结果把生产环境的索引也删了…… 从那以后,我养成了给索引加别名的习惯。

3.2.4 修改索引

索引创建后,大部分设置不能改。但你可以动态调整副本数:

PUT /user/_settings
{
  "number_of_replicas": 2
}

3.3 文档的 CRUD

文档,就是索引里的“一行数据”。

3.3.1 新增文档

指定 ID 新增:

PUT /user/_doc/1
{
  "name": "张三",
  "age": 28,
  "city": "北京"
}

不指定 ID,让 ES 自动生成:

POST /user/_doc
{
  "name": "李四",
  "age": 32,
  "city": "上海"
}

这里有个区别:PUT 必须带 ID,POST 可以不带。我个人习惯用 POST 新增,让 ES 自己生成 ID,省得我操心。

3.3.2 查询文档

GET /user/_doc/1

返回结果里有个 _source 字段,里面就是你的原始数据。如果你只想看数据,不想看元信息:

GET /user/_doc/1?_source

3.3.3 更新文档

全量替换(覆盖):

PUT /user/_doc/1
{
  "name": "张三丰",
  "age": 100
}

局部更新(只改某个字段):

POST /user/_doc/1/_update
{
  "doc": {
    "age": 29
  }
}
重点: PUT 是全量替换,如果你只传了 nameage,那 city 字段就没了。而 _update 是局部更新,只修改你指定的字段。

3.3.4 删除文档

DELETE /user/_doc/1

3.4 批量操作(Bulk API)

单个操作太慢了。比如你要导入 100 万条数据,一条一条发请求,那得等到猴年马月?

Bulk API 就是用来解决这个问题的。它允许你一次发送多个操作。

格式有点特殊,是 NDJSON(每行一个 JSON,最后空一行):

POST /_bulk
{ "index" : { "_index" : "user", "_id" : "1" } }
{ "name" : "王五", "age" : 25, "city" : "广州" }
{ "index" : { "_index" : "user", "_id" : "2" } }
{ "name" : "赵六", "age" : 30, "city" : "深圳" }
{ "delete" : { "_index" : "user", "_id" : "3" } }

你看,每一对 JSON 代表一个操作:

  • 第一行是操作类型(index、create、update、delete)
  • 第二行是数据(delete 不需要数据)

批量操作也可以指定索引:

POST /user/_bulk
{ "index" : { "_id" : "4" } }
{ "name" : "钱七", "age" : 22, "city" : "杭州" }
{ "update" : { "_id" : "1" } }
{ "doc" : { "age" : 26 } }
避坑指南: 我曾经在批量导入时,把数据量一次性搞到 10 万条。结果 ES 直接 OOM 了。后来我学乖了,每批控制在 5000-10000 条,内存压力小很多。另外,Bulk 请求的 body 里不能有换行符(除了行之间的 \n),否则会解析失败。

好了,基础操作就这些。你想想看,是不是很简单?

说白了,ES 的 API 就是一套 HTTP 接口。你只要记住:PUT 是增/改,POST 是增/局部改,GET 是查,DELETE 是删。

下一章,咱们聊聊 ES 的查询语法。那才是真正体现搜索引擎能力的地方。