在 ES 7 中新增索引:
PUT student
{
"mappings" : {
"properties" : {
"name" : {
"type" : "keyword"
},
"age" : {
"type" : "integer"
}
}
},
"settings" : {
"index" : {
"number_of_shards" : 1,
"number_of_replicas" : 0
}
}
}
使用 POST
POST 用于更新数据,如果不存在,则会创建。
添加数据示例1:
# 请求
POST student/_doc
{
"name": "张三"
}
# 响应
{
"_index" : "student",
"_type" : "_doc",
"_id" : "gCJ8Tm4Buf-uwlbZzC7C",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 1,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 0,
"_primary_term" : 1
}
添加数据示例2:
指定 _id 为 2。
# 请求
POST student/_doc/2
{
"name": "李四"
}
# 响应
{
"_index" : "student",
"_type" : "_doc",
"_id" : "2",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 1,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 1,
"_primary_term" : 1
}
一个错误的更新数据方式
# 请求
GET student/_doc/2
# 响应
{
"_index" : "student",
"_type" : "_doc",
"_id" : "2",
"_version" : 1,
"_seq_no" : 1,
"_primary_term" : 1,
"found" : true,
"_source" : {
"name" : "李四"
}
}
可以看到没有 age 字段。
更新 age:
# 请求
POST student/_doc/2
{
"age": 10
}
# 响应
{
"_index" : "student",
"_type" : "_doc",
"_id" : "2",
"_version" : 2,
"result" : "updated",
"_shards" : {
"total" : 1,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 2,
"_primary_term" : 1
}
再次请求数据:
GET student/_doc/2
# {
"_index" : "student",
"_type" : "_doc",
"_id" : "2",
"_version" : 2,
"_seq_no" : 2,
"_primary_term" : 1,
"found" : true,
"_source" : {
"age" : 10
}
}
结果是 version 从1变成了2,而 name 字段不见了。
原因是 POST student/_doc/2
这种语法的效果是覆盖数据。可以理解为先把原文档删除,再索引新文档。
POST student/_doc/2
的效果相同。
使用 _update
更新文档
如何在 name 不消失的情况下更新 age 呢?用 _update
。
示例:
# 请求1
POST student/_doc/2
{
"name": "李四"
}
# 请求2: 新增 age
POST student/_doc/2/_update
{
"doc": {
"age": 10
}
}
# 查询
GET student/_doc/2
# 查询结果
{
"_index" : "student",
"_type" : "_doc",
"_id" : "2",
"_version" : 6,
"_seq_no" : 6,
"_primary_term" : 1,
"found" : true,
"_source" : {
"name" : "李四",
"age" : 10
}
}
POST student/_doc/2/_update
这种方式会报错:
#! Deprecation: [types removal] Specifying types in document update requests is deprecated, use the endpoint /{index}/_update/{id} instead.
所以,建议用下面的方法:
POST student/_update/2
{
"doc": {
"age": 11
}
}
使用 _update
时,ES 做了下面几件事:
- 从旧文档构建 JSON
- 更改该 JSON
- 删除旧文档
- 索引一个新文档
使用 _update_by_query 更新文档
POST student/_update_by_query
{
"query": {
"match": {
"_id": 2
}
},
"script": {
"source": "ctx._source.age = 12"
}
}
用下面的方法也行,但会有告警:
POST student/_update_by_query
{
"query": {
"match": {
"_id": 2
}
},
"script": {
"inline": "ctx._source.age = 12"
}
}
执行时告警信息如下:
#! Deprecation: Deprecated field [inline] used, expected [source] instead
也就 inline
已经被废弃了,应该使用 source
。 所以,最正确的方式是:
POST student/_update_by_query
{
"query": {
"match": {
"_id": 2
}
},
"script": {
"source": "ctx._source.age = 12"
}
}