为了方便其他语言的整合Elasticsearch为开发者提供了一套基于Http协议的Restful接口,只需要构造rest请求并解析请求返回的json即可实现访问Elasticsearch服务器。Elasticsearch的API接口功能丰富,包含集群、监控、部署管理等,也包含常用的文档、索引操作。

REST API - 很容易被各种语言调用

文档的操作

操作 REST API 参数
Index PUT my_index/_doc/1 {"user":"mike","comment":"You Konw,for search"}
Create PUT my_index/_create/1
POST my_index/_doc(不指定ID,自动生成)
{"user":"mike","comment":"You Konw,for search"}
{"user":"mike","comment":"You Konw,for search"}
Read GET my_index/_doc/1
Update POST my_index/_update/1 {"doc":{"user":"mike","comment":"You Konw,for search"}}
Delete DELETE my_index/_doc/1
  • Type 名,约定都用_doc
  • Create - 如果ID已经存在,会失败
  • Index - 如果 ID 不存在 ,创建新的文档。否则,先删除现有的文档,再创建新的文档,版本会增加
  • Update -文档必须已经存在,更新只会对相应字段做增量修改

Create 一个文档

指定文档ID

PUT users/_create/1
{
  "firstName":"Jack",
  "lastName":"Johnson",
  "tags":["guitar","skateboard"]
}
or # 手动设置 type 是 create
PUT users/_doc/1?op_type=create
{
  "firstName":"Jack",
  "lastName":"Johnson",
  "tags":["guitar","skateboard"]
}

返回结果:

{
  "_index" : "users",
  "_type" : "_doc",
  "_id" : "1", # 手动指定的文档编号
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 0,
  "_primary_term" : 1
}

如果已经存在会报错:

{
  "error": {
    "root_cause": [
      {
        "type": "version_conflict_engine_exception",
        "reason": "[1]: version conflict, document already exists (current version [1])",
        "index_uuid": "nzRRiahvRtSNNSf7oohKEQ",
        "shard": "0",
        "index": "users"
      }
    ],
    "type": "version_conflict_engine_exception",
    "reason": "[1]: version conflict, document already exists (current version [1])",
    "index_uuid": "nzRRiahvRtSNNSf7oohKEQ",
    "shard": "0",
    "index": "users"
  },
  "status": 409
}

自动生成ID

POST users/_doc
{
  "firstName":"Tom",
  "lastName":"Jerry",
  "tags":["cat","rat"]
}

返回结果:

{
  "_index" : "users",
  "_type" : "_doc",
  "_id" : "VWsV9WwBOKERAIDEZ-sc", # 自动生成的文档编号
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 1,
  "_primary_term" : 1
}

Get 一个文档

找到文档,返回 HTTP 200

  • 文档元信息
    • _index/_type/
    • 版本信息,同一个ID的文档 即使被删除 Version号也会不断增加
    • source 中默认包含了 文档的所有原始信息
GET users/_doc/1

返回结果

{
  "_index" : "users", # 索引名称
  "_type" : "_doc", # type
  "_id" : "1", # 主键
  "_version" : 1, # 版本
  "_seq_no" : 0,
  "_primary_term" : 1,
  "found" : true,
  "_source" : { # 原始信息
    "firstName" : "Jack",
    "lastName" : "Johnson",
    "tags" : [
      "guitar",
      "skateboard"
    ]
  }
}

找不到文档,返回HTTP 404

GET users/_doc/2

返回结果:

{
  "_index" : "users",
  "_type" : "_doc",
  "_id" : "2",
  "found" : false
}

Index(索引) 文档

Index 和Create 不一样的地方: 如果文档不存在,就索引新的文档。否则现有文档会被删除,新的文档被索引。版本信息+1;

put 文档

PUT users/_doc/1
{
  "tags":["guitar","skateboard","reading"]
}

返回结果:

{
  "_index" : "users",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 2,
  "result" : "updated",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 2,
  "_primary_term" : 1
}

获取操作后的文档

GET users/_doc/1

返回结果:

{
  "_index" : "users",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 2,
  "_seq_no" : 2,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "tags" : [
      "guitar",
      "skateboard",
      "reading"
    ]
  }
}

Update 文档

  • Update方法不会删除原来的文档,而是实现真正的数据更新
  • Post方法 / Payload 需要包含在 doc

更新文档

POST users/_update/1
{
  "doc":{
    "albums":["album1","album2"]
  }
}

返回结果:

{
  "_index" : "users",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 3,
  "result" : "updated",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 3,
  "_primary_term" : 1
}

获取更新后的文档

GET users/_doc/1

返回结果:

{
  "_index" : "users",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 3,
  "_seq_no" : 3,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "tags" : [
      "guitar",
      "skateboard",
      "reading"
    ],
    "albums" : [
      "album1",
      "album2"
    ]
  }
}

put 和 update 的区别

  • update 会将数据更新,未修改的字段保持愿值
  • put 会直接覆盖掉元数据(元数据删除掉后,重新索引)

delete 文档

DELETE users/_doc/1

返回结果:

{
  "_index" : "users",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 7,
  "result" : "deleted",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 7,
  "_primary_term" : 3
}

Indices

创建索引

PUT movies

返回结果:

{
  "acknowledged" : true,
  "shards_acknowledged" : true,
  "index" : "movies"
}

删除索引

DELETE movies

返回结果:

{
  "acknowledged" : true
}

批量操作

Bulk API

在一个REST请求的时候,重新建立网络开销是非常损耗性能的,Bulk API的核心思想就是,在一次请求中,做不同的操作。

  • 支持在一次API 调用中,对不同对索引进行操作
  • 支持四种类型操作
    • Index
    • Create
    • Update
    • Delete
  • 可以在URI中指定Index,也可以在请求的Payload中进行
  • 操作中单条操作失败,并不会影响其他操作
  • 返回结果包括了每一条操作执行的结果

Demo

请求:

POST _bulk # 这个是请求地址
# 索引一个文档  指明索引是test 文档编号(主键)是 1 字段名为 field1 值为 value1
{"index":{"_index":"test","_id":"1"}}
{"field1":"value1"}

# 删除 一个文档 指明索引是 test 文档编号(主键)是2
{"delete":{"_index":"test","_id":"2"}}

# 创建一个文档,指明索引是test2 文档编号(主键)是 3  字段名为 field1 值为 value3
{"create":{"_index":"test2","_id":"3"}}
{"field1":"value3"}

# 更新一个文档 指明索引是test 文档编号(主键)是1 修改的字段是 field2 值为 value2
{"update":{"_index":"test","_id":"1"}}
{"doc": {"field2":"value2"}}

返回结果:

{
  "took" : 288,
  "errors" : false,
  "items" : [
	# 第一个操作的返回值 创建成功,HTTP响应 201
    {
      "index" : {
        "_index" : "test",
        "_type" : "_doc",
        "_id" : "1",
        "_version" : 1,
        "result" : "created",  # 创建成功
        "_shards" : {
          "total" : 2,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 0,
        "_primary_term" : 1,
        "status" : 201 # HTTP响应码
      }
    },
	# 第二个操作的返回值 删除失败,HTTP响应 404
    {
      "delete" : {
        "_index" : "test",
        "_type" : "_doc",
        "_id" : "2",
        "_version" : 1,
        "result" : "not_found", # 文档不存在
        "_shards" : {
          "total" : 2,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 1,
        "_primary_term" : 1,
        "status" : 404 # HTTP响应码
      }
    },
		# 第三个操作的返回值 创建成功,HTTP响应 201
    {
      "create" : {
        "_index" : "test2",
        "_type" : "_doc",
        "_id" : "3",
        "_version" : 1,
        "result" : "created", # 创建成功
        "_shards" : {
          "total" : 2,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 0,
        "_primary_term" : 1,
        "status" : 201  # HTTP响应码
      }
    },
		# 第四个操作的返回值 更新成功,HTTP响应 200
    {
      "update" : {
        "_index" : "test",
        "_type" : "_doc",
        "_id" : "1",
        "_version" : 2,
        "result" : "updated", # 更新成功
        "_shards" : {
          "total" : 2,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 2,
        "_primary_term" : 1,
        "status" : 200 # HTTP响应码
      }
    }
  ]
}

mget 批量读取

批量读取可以减少网络连接锁产生的开销。提高性能

Demo

请求:

GET _mget
{
    "docs":[
        {
            "_index":"test",
            "_id":1
        },
        {
            "_index":"test2",
            "_id":1
        }
    ]
}

返回结果:

{
  "docs" : [
    {
      "_index" : "test",
      "_type" : "_doc",
      "_id" : "1",
      "_version" : 2,
      "_seq_no" : 2,
      "_primary_term" : 1,
      "found" : true,
      "_source" : {
        "field1" : "value1",
        "field2" : "value2"
      }
    },
    {
      "_index" : "test2",
      "_type" : "_doc",
      "_id" : "1",
      "found" : false    //未找到 只有id为3的没有id为1的
    }
  ]
}

msearch 批量查询

Demo

请求:

POST test/_msearch    //在 test 索引上查查询
{}
{"query":{"match_all":{}},"size":1} // 查询所有,只返回一条
{"index":"test2"}    //可以指定其他的索引,这个是 test2索引
{"query":{"match_all":{}},"size":1}

返回结果:

{
  "took" : 9,
  "responses" : [
    {
      "took" : 2,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 1,
          "relation" : "eq"
        },
        "max_score" : 1.0,
        "hits" : [
          {
            "_index" : "test",
            "_type" : "_doc",
            "_id" : "1",
            "_score" : 1.0,
            "_source" : {
              "field1" : "value1",
              "field2" : "value2"
            }
          }
        ]
      },
      "status" : 200
    },
    {
      "took" : 1,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 1,
          "relation" : "eq"
        },
        "max_score" : 1.0,
        "hits" : [
          {
            "_index" : "test2",
            "_type" : "_doc",
            "_id" : "3",
            "_score" : 1.0,
            "_source" : {
              "field1" : "value3"
            }
          }
        ]
      },
      "status" : 200
    }
  ]
}

常见错误返回

问题 原因
无法连接 网络故障或集群挂了
连接无法关闭 网络故障或节点出错
429 集群过于繁忙
4xx 请求体格式有错
500 集群内部错误

参考链接