#Elasticsearch# 文章列表 Elasticsearch 介绍 Elasticsearch 7:快速上手 Elasticsearch 7:关于 Index、Type、Document Elasticsearch 7:安装与启动 Elasticsearch 7:Kibana 的使用 Elasticsearch 7:下载历史版本 Elasticsearch 7:文档唯一性 Elasticsearch 7:默认端口与端口设置 Elasticsearch 7:创建和删除索引 Elasticsearch 7:自定义 mapping 和 settings Elasticsearch 7:设置索引副本数量和分片数量 Elasticsearch 7:查看所有索引 Elasticsearch 7:数据类型 Elasticsearch 7:字符串类型 keyword 、text Elasticsearch 7:数组 Elasticsearch 7:添加和更新文档 Elasticsearch 7:通过 _bulk 批量添加文档 Elasticsearch 7:使用 from 、size 进行分页查询 Elasticsearch 7:查询中使用 sort 进行排序 Elasticsearch 7:查询结果只展示部分字段 Elasticsearch 7:查询结果中展示 _version 字段 Elasticsearch 7:使用 ignore_above 限制字符串长度 Elasticsearch 7:动态映射 Elasticsearch 7:doc_values 属性 Elasticsearch 7:刷新周期 refresh_interval Elasticsearch 7:使用 _refresh 刷新索引 Elasticsearch 7:分片(shard)限制 Elasticsearch 7:使用 _cat thread_pool 查询线程池运行情况 Elasticsearch 7:事务日志 translog Elasticsearch 7:文档 _id 的长度限制 Elasticsearch 7:分片 shard Elasticsearch 7:滚动查询 Elasticsearch 7:聚合查询 Elasticsearch 7:索引模板 Elasticsearch 7:获取文档所属的 shard Elasticsearch 7:获取版本号 Elasticsearch 7:获取指定 shard 中的文档 Elasticsearch 7:获取 shard 统计信息 Elasticsearch 7:搜索实战 Elasticsearch 7:Python 客户端 Elasticsearch 7:Java TransportClient API 客户端 Elasticsearch 7:Java REST Client API 客户端 Elasticsearch:将 SQL 转换为 DSL Elasticsearch 6 快速上手 Elasticsearch 5 快速上手 Elasticsearch 5:禁止自动创建索引 Elasticsearch 5:禁止动态增加字段 Elasticsearch 产品版本支持周期 基于 Elasticsearch 的站内搜索引擎实战

Elasticsearch 7:添加和更新文档


#Elasticsearch#


在 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 做了下面几件事:

  1. 从旧文档构建 JSON
  2. 更改该 JSON
  3. 删除旧文档
  4. 索引一个新文档

使用 _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"
  }
}

( 本文完 )