Elastic Stack 实战教程 1:Elastic Stack 8 快速上手
本系列 Elastic Stack 实战教程总共涵盖 5 个实验,目的是帮助初学者快速掌握 Elastic Stack 的基本技能。
云起实验室在线体验地址:https://developer.aliyun.com/adc/scenarioSeries/24e7a7a4d56741d0bdcb3ee73c9c22f1
- 实验 1:Elastic Stack 8 快速上手
- 实验 2:ILM 索引生命周期管理
- 实验 3:快照备份与恢复
- 实验 4:使用 Fleet 管理 Elastic Agent 监控应用
- 实验 5:Elasticsearch Java API Client 开发
1 Elastic Stack 介绍
Elastic Stack 的核心产品包括 Elasticsearch、Kibana、Beats 和 Logstash,可以帮助用户安全可靠地获取任何来源、任何格式的数据,并实时地对数据进行搜索、分析和可视化。
Elasticsearch 是一个分布式、RESTful 风格的搜索和数据分析引擎,Elasticsearch 作为 Elastic Stack 的核心,集中存储数据。
Kibana 提供了酷炫的可视化界面, 使用 Kibana 可以对 Elasticsearch 索引中的数据进行搜索、查看以及交互操作,用户可以利用图表、表格以及地图对数据进行多元化的分析和呈现。
Beats 和 Logstash 提供了数据摄取的功能。其中 Beats 是一个轻量级的数据摄取工具,Logstash 则提供了类似于 ELT 的功能。
在下面的实验中,将会介绍如何在 ECS 实例上部署 Elasticsearch 和 Kibana,以及 Elasticsearch 常用 API 的使用方法。
2 部署 Elasticsearch
本小节将指导您如何部署一个单节点的 Elasticsearch 集群。
出于安全原因,Elasticsearch 默认不允许使用 root 用户启动。执行以下命令,创建 elastic 用户,设置密码为 elastic123 ,并切换到该用户。
useradd -s /bin/bash -m elastic
echo "elastic:elastic123" | chpasswd
su - elastic
下载和解压 Elasticsearch 安装文件。
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.2.3-linux-x86_64.tar.gz
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.2.3-linux-x86_64.tar.gz.sha512
shasum -a 512 -c elasticsearch-8.2.3-linux-x86_64.tar.gz.sha512
tar -xzf elasticsearch-8.2.3-linux-x86_64.tar.gz
cd elasticsearch-8.2.3/
Elasticsearch 目录结构如下所示。
执行如下命令,启动 Elasticsearch。
./bin/elasticsearch
启动成功后,会输出以下内容,保存好以下两个内容:
- elastic 用户密码。
- Kibana 注册 token。
在启动过程中 Elasticsearch 需要连接公网获取 IP 地址地理位置的相关信息,由于网络原因可能导致数据下载失败而产生以下报错,该报错对 Elasticsearch 运行没有影响,用户可以忽略。
浏览器输入 https://<ESC 公网 IP>:9200
访问 Elasticsearch,注意本场景中提供了两台 ECS 实例,请填写正确的 ECS 公网 IP 地址。输入用户名:elastic,密码:VMtfK-YaNOptoBDnNaRY(根据上面输出填写)。用户认证通过后,会显示以下内容:
- name: 节点名,默认使用主机名作为节点名。
- cluster_name: 集群名,默认的集群名是 elasticsearch,同一个集群中的所有节点的 cluster.name 要保持一致。
- cluster_uuid: 集群的唯一标识符。
- version: 版本信息。
至此我们已经成功部署了一个单节点的 Elasticsearch 集群。
3 部署 Kibana
本小节将指导您如何部署 Kibana 并连接到 Elasticsearch。
打开一个新的终端, 切换到 elastic 用户。
su - elastic
执行如下命令,下载和解压 Kibana 安装文件。
curl -O https://artifacts.elastic.co/downloads/kibana/kibana-8.2.3-linux-x86_64.tar.gz
curl https://artifacts.elastic.co/downloads/kibana/kibana-8.2.3-linux-x86_64.tar.gz.sha512 | shasum -a 512 -c -
tar -xzf kibana-8.2.3-linux-x86_64.tar.gz
cd kibana-8.2.3/
Kibana 目录结构如下所示:
编辑 config/kibana.yml 配置文件,修改以下内容,允许 Kibana 服务监听本机所有 IP 地址。
server.host: "0.0.0.0"
执行如下命令,启动 Kibana。
./bin/kibana
启动成功后,会输出以下内容。
浏览器输入 http://<ESC 公网 IP>:5601/?code=321491
访问 Kibana 界面,code=321491 修改为上图终端输出的内容。在 Enrollment token 输入框中填入第 1 小节启动 Elasticsearch 后输出的 Kibana 注册 token,然后点击 Configure Elastic。
接着 Kibana 会自动完成注册设置。
Kibana 注册成功后会出现登录界面,输入 elastic 用户名密码登录 Elasticsearch。
在注册成功后,在 config/kibana.yml 配置文件中会自动添加 Elasticsearch 相关的连接信息和 SSL 证书,用户无需关注。
4 往集群中注册新节点
本小节将指导您如何往 Elasticsearch 集群中注册新节点。
首先在第一个终端,键盘按 Ctrl + C 停止在前台运行的 Elasticsearch 进程。
4.1 修改第一个节点配置
默认情况下,Elasticsearch transport 服务的 9300 端口只在 127.0.0.1 上监听。如果要想和其他节点进行交互,我们需要更改当前节点的 config/elasticsearch.yml 文件,修改内容如下。
transport.host: 0.0.0.0
当允许 transport 服务在非环回地址监听后,Elasticsearch 将处于生产模式,在启动之前需要进行一些引导检查,我们需要修改一些系统参数确保能够通过检查。
在当前 elastic 用户下执行 exit
命令退回 root 用户,在 root 用户修改以下系统参数。
增加进程可使用的最大内存映射区域数,编辑 /etc/sysctl.conf 文件,添加以下内容。
vm.max_map_count=262144
执行以下命令立即生效:
sysctl -p
增加进程可使用的最大文件描述符数量,编辑 /etc/security/limits.conf 文件,添加以下内容。
elastic - nofile 65535
执行以下命令立即生效:
ulimit -n 65535
切换到 elastic 用户。
su - elastic
重新启动 Elasticsearch,-d 参数表示在后台运行 Elasticsearch。
cd elasticsearch-8.2.3
./bin/elasticsearch -d
执行 tail -f logs/elasticsearch.log
命令可以查看 Elasticsearch 的启动日志。
确认 Elasticsearch 启动成功以后,执行以下命令,生成新的注册 token,用于注册新节点到 Elasticsearch 集群。
bin/elasticsearch-create-enrollment-token -s node
# 返回的 token
eyJ2ZXIiOiI4LjIuMyIsImFkciI6WyIxMC4yMC42MS4xNzk6OTIwMCJdLCJmZ3IiOiJiYTM3YjVmMTU4YTc4MmFiNWQ3N2M0YWI1ODFiMjc1ZjMxMTYxZDcxOWQ2YTA2NTU1NGU0MjBjYzNlZTc3YzMwIiwia2V5IjoiY1A3WGxJRUJFLU9sOTh0Qm5Deno6UXZTWEdOZ3BTYktaWXdic19pTS1fUSJ9
4.2 注册新节点
接下来配置新节点,打开一个新的终端, 执行 ssh root@<ESC 公网 IP>
命令登录到另一个节点上。
在 root 用户下修改以下系统参数。 增加进程可使用的最大内存映射区域数,编辑 /etc/sysctl.conf 文件,添加以下内容。
vm.max_map_count=262144
执行以下命令立即生效:
sysctl -p
增加进程可使用的最大文件描述符数量,编辑 /etc/security/limits.conf 文件,添加以下内容。
elastic - nofile 65535
执行以下命令立即生效:
ulimit -n 65535
执行以下命令,创建 elastic 用户,设置密码为 elastic123 ,并切换到该用户。
useradd -s /bin/bash -m elastic
echo "elastic:elastic123" | chpasswd
su - elastic
下载和解压 Elasticsearch 安装文件。
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.2.3-linux-x86_64.tar.gz
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.2.3-linux-x86_64.tar.gz.sha512
shasum -a 512 -c elasticsearch-8.2.3-linux-x86_64.tar.gz.sha512
tar -xzf elasticsearch-8.2.3-linux-x86_64.tar.gz
cd elasticsearch-8.2.3/
在当前节点的 config/elasticsearch.yml 文件中,添加以下内容。
transport.host: 0.0.0.0
执行以下命令,启动新节点,并往 Elasticsearch 集群进行注册,在 --enrollment-token
参数后面跟上前面生成的 token。
bin/elasticsearch --enrollment-token eyJ2ZXIiOiI4LjIuMyIsImFkciI6WyIxMC4yMC42MS4xNzk6OTIwMCJdLCJmZ3IiOiJiYTM3YjVmMTU4YTc4MmFiNWQ3N2M0YWI1ODFiMjc1ZjMxMTYxZDcxOWQ2YTA2NTU1NGU0MjBjYzNlZTc3YzMwIiwia2V5IjoiY1A3WGxJRUJFLU9sOTh0Qm5Deno6UXZTWEdOZ3BTYktaWXdic19pTS1fUSJ9
在 Kibana 的 Dev Tools 中执行以下命令,查询集群中的节点,可以看到第二个节点已经成功加入集群。默认使用主机名作为节点名。
GET _cat/nodes?v
# 返回结果
ip heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name
10.20.61.179 21 95 10 0.14 0.27 0.20 cdfhilmrstw * elastic-demo
10.20.61.180 6 85 2 0.74 0.28 0.09 cdfhilmrstw - node-2
在注册成功后,在 config/elasticsearch.yml 配置文件中会自动添加 Elasticsearch 相关的配置信息,用户无需关注。
节点的所需 SSL 证书也会自动拷贝到新节点上。
5 写入文档
本小节将指导您如何将数据写入 Elasticsearch。
Elasticsearch 具有 Schemaless的能力,能够自动检测 JSON 源数据的类型并为数据中的新字段创建新的映射。正是由于这种灵活的特性,使得我们可以不用事先为索引定义 mapping(映射)就可以往索引中写入数据。
点击 Management -> Dev Tools -> Console,打开 Kibana Console 界面。在左侧面板中执行以下命令,往 books 索引中写入一条文档。Elasticsearch 会自动帮我们创建 books 索引。
# 写入单条文档
POST books/_doc
{
"title": "Programming Kubernetes",
"isbn": "9781617297618",
"pageCount": 345,
"category": "Cloud Native"
}
在右侧 面板会返回响应结果,可以看到文档已经被成功创建了,doc id 是随机生成的 YTeEhYEBGHa5rBjoiL-Q。
如果想要在写入文档时指定 doc id,可以使用 PUT <index-name>/_doc/<doc-id>
。如果指定 id 的文档不存在,则直接创建新的文档;否则先删除现有文档,再创建新的文档,同时文档版本号(_version, _seq_no)会增加。
# 设置写入的 doc id 为 1
PUT books/_doc/1
{
"title": "Istio in Action",
"isbn": "9781617295829",
"pageCount": 480,
"category": "Cloud Native"
}
使用 bulk API 可以在单次请求中批量写入多条文档,这样能极大减少写入请求的网络开销。
POST books/_bulk
{"index": {"_id": 2}}
{"title":"Elasticsearch in Action","isbn":"9781617299858","pageCount":475,"category": "Search"}
{"index": {"_id": 3}}
{"title":"Relevant Search","isbn":"9781617292774","pageCount":360,"category": "Search"}
{"index": {"_id": 4}}
{"title":"Modern Java in Action","isbn":"9781617293566","pageCount":592,"category": "Java"}
6 查询文档
本小节将指导您如何查询 Elasticsearch 中的数据。
使用 GET <index-name>/_doc/<doc-id>
可以获取索引中指定 doc id 的文档。执行以下命令,获取 doc id 为 1 的文档。
GET books/_doc/1
响应结果如下,除了返回文档的内容以外,还包含了一些元数据字段:
- _index: 文档所属的索引名。
- _id: 文档 id。
- _version: 文档的版本号,_version 属于单个文档,修改删除操作会在当前文档的 _version 基础上自增 1。
- _seq_no: 索引的版本号,_seq_no 属于整个索引,修改删除操作会整个索引的 _seq_no 基础上自增 1。
- _primary_term: 每当主分片发生重新分配时(例如故障转移,主分片选举),_primary_term 会自增 1。该参数主要是为了防止主分片重新分配到新节点后,原主分片所在的节点恢复后覆盖新节点上主分片写入的数据。
- _source: 文档原始的 JSON 数据。
{
"_index" : "books", // 索引名
"_id" : "1",
"_version" : 2,
"_seq_no" : 3,
"_primary_term" : 1,
"found" : true,
"_source" : { // 文档内容
"title" : "Istio in Action",
"isbn" : "9781617295829",
"pageCount" : 480,
"category" : "Cloud Native"
}
}
查询 books 索引,不指定任何过滤条件,默认最多返回 10 条文档。
GET books/_search
返回了当前索引中的全部 4 条文档。
- took: 搜索请求总共耗费了多少毫秒。
- timed_out: 查询是否超时。如果超时,Elasticsearch 将会返回超时前已经成功从每个分片获取的结果。
- _shards: 查询的分片计数。
- total: 需要查询的分片总数,包括未分配的分片。
- successful: 执行请求成功的分片数。
- skipped: 跳过的分片数,Elasticsearch 在查询前先会通过轻量级的检查判断分片上是否含符合条件的文档,通常发生在查询中带有 range 过滤条件的情况下。
- failed: 执行请求失败的分片数。
- hits: 返回的文档和元数据。
- total: 匹配到的文档总数。
- max_score: 返回最高的文档分数。
- hits: 文档对象数组。
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 5,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "books",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"title" : "Istio in Action",
"isbn" : "9781617295829",
"pageCount" : 480,
"category" : "Cloud Native"
}
},
{
"_index" : "books",
"_id" : "2",
"_score" : 1.0,
"_source" : {
"title" : "Elasticsearch in Action",
"isbn" : "9781617299858",
"pageCount" : 475,
"category" : "Search"
}
},
{
"_index" : "books",
"_id" : "3",
"_score" : 1.0,
"_source" : {
"title" : "Relevant Search",
"isbn" : "9781617292774",
"pageCount" : 360,
"category" : "Search"
}
},
{
"_index" : "books",
"_id" : "4",
"_score" : 1.0,
"_source" : {
"title" : "Modern Java in Action",
"isbn" : "9781617293566",
"pageCount" : 592,
"category" : "Java"
}
},
{
"_index" : "books",
"_id" : "ZDfNjoEBGHa5rBjoYL_5",
"_score" : 1.0,
"_source" : {
"title" : "Programming Kubernetes",
"isbn" : "9781617297618",
"pageCount" : 345,
"category" : "Cloud Native"
}
}
]
}
}
Elasticsearch 在不设置字段映射的情况下, 默认会将字符串类型的字段设置成 text 类型,并加上一个 keyword 子字段,子字段的类型是 keyword。text 类型的字段默认使用 standard 分析器解析文本,按照 Unicode 文本分割算法对文本进行切分,去除标点符号,并将切分后的单词转换为小写,主要用于全文搜索;keyword 类型的字段使用 keyword 分析器解析文本,不对文本进行切分,保留原始的文本内容,用于精确匹配和聚合查询。
使用 match 查询 title 字段中含有 action 的文档,不区分大小写。
GET books/_search
{
"query": {
"match": {
"title": "action"
}
}
}
这次只返回了 title 中含有 action 的 3 条文档。
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : 0.35667494,
"hits" : [
{
"_index" : "books",
"_id" : "1",
"_score" : 0.35667494,
"_source" : {
"title" : "Istio in Action",
"isbn" : "9781617295829",
"pageCount" : 480,
"category" : "Cloud Native"
}
},
{
"_index" : "books",
"_id" : "2",
"_score" : 0.35667494,
"_source" : {
"title" : "Elasticsearch in Action",
"isbn" : "9781617299858",
"pageCount" : 475,
"category" : "Search"
}
},
{
"_index" : "books",
"_id" : "4",
"_score" : 0.31387398,
"_source" : {
"title" : "Modern Java in Action",
"isbn" : "9781617293566",
"pageCount" : 592,
"category" : "Java"
}
}
]
}
}
使用 term 查询精确匹配 category.keyword 字段值是 Cloud Native 的文档。上面介绍到 keyword 类型的字段保留原始文本,用于精确匹配,因此这里的查询区分大小写,如果查询 cloud native 将匹配不到文档。
GET books/_search
{
"query": {
"term": {
"category.keyword": {
"value": "Cloud Native"
}
}
}
}
返回结果如下,匹配到了 2 条文档。
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 0.87546873,
"hits" : [
{
"_index" : "books",
"_id" : "1",
"_score" : 0.87546873,
"_source" : {
"title" : "Istio in Action",
"isbn" : "9781617295829",
"pageCount" : 480,
"category" : "Cloud Native"
}
},
{
"_index" : "books",
"_id" : "ZDfNjoEBGHa5rBjoYL_5",
"_score" : 0.87546873,
"_source" : {
"title" : "Programming Kubernetes",
"isbn" : "9781617297618",
"pageCount" : 345,
"category" : "Cloud Native"
}
}
]
}
}
如果我们想同时通过多个条件查询文档,可以使用 bool 组 合查询。bool 查询接受以下 4 个参数:
- must: must 中的所有条件都要符合,计算相关性得分。
- must_not: 排除所有符合 must_not 条件的文档,不计算相关性得分。
- filter: 只过滤符合条件的文档,不计算相关性得分。
- should:
- 情况 1: bool 查询中只包含 should ,不包含 must 查询,此时文档必须满足至少一个条件,minimum_should_match 可以控制满足条件的个数或者百分比。
- 情况 2:bool 查询中同时包含 should 和 must 查询,此时文档不必满足 should 中的条件,但是如果满足条件,会增加相关性得分。
下面的查询表示同时满足 title 字段中含有 action 以及 category.keyword 字段值是 Cloud Native 两个条件的文档才算匹配。
GET books/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"title": "action"
}
},
{
"term": {
"category.keyword": {
"value": "Cloud Native"
}
}
}
]
}
}
}
返回结果如下,只有 1 条文档同时满足以上两个条件。
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.3991625,
"hits" : [
{
"_index" : "books",
"_id" : "1",
"_score" : 1.3991625,
"_source" : {
"title" : "Istio in Action",
"isbn" : "9781617295829",
"pageCount" : 480,
"category" : "Cloud Native"
}
}
]
}
}
Elasticsearch 除了文本搜索以外,还支持聚合查询,可以帮助我们对数据进行分析。例如我们可以通过以下命令查询 books 索引中每种类别书籍的数量。
GET books/_search
{
"size": 0, // 不返回文档,只返回聚合结果
"aggs": { // 聚合查询
"my_category_agg": {
"terms": {
"field": "category.keyword",
"size": 10
}
}
}
}
返回结果如下,可以看到 Cloud Native 类别的书籍有 2 个,Search 类别的书籍有 1 个, Java 类别的书籍有 1 个。
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 5,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"my_category_agg" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "Cloud Native",
"doc_count" : 2
},
{
"key" : "Search",
"doc_count" : 2
},
{
"key" : "Java",
"doc_count" : 1
}
]
}
}
}
7 更新文档
本小节将指导您如何更新 Elasticsearch 中的数据。
使用 PUT <index-name>/_doc/<doc-id>
这种语法的效果是覆盖数据,可以理解为先删除现有文档,再创建新的文档。 如果该 doc id 的文档不存在,则创建一个新的文档。
PUT books/_doc/1
{
"title": "Cloud Native Patterns",
"isbn": "9781617294297",
"category": "Cloud Native"
}
查询 doc id 为 1 的这条文档。
GET books/_doc/1
返回结果如下,新的文档中只含有我们更新时指定 3 个字段,而原始文档中的 pageCount 字段消失了。
{
"_index" : "books",
"_id" : "1",
"_version" : 2,
"_seq_no" : 5,
"_primary_term" : 1,
"found" : true,
"_source" : {
"title" : "Cloud Native Patterns",
"isbn" : "9781617294297",
"category" : "Cloud Native"
}
}
那么如何在不影响文档中其他字段的情况下对文档进行更新呢?可以使用 PUT <index-name>/_update/<doc-id>
语法,在请求体的 doc 参数中指定要更新的字段内容。
POST books/_update/1
{
"doc": { // 指定要更新的字段内容
"pageCount": 400
}
}
查询 doc id 为 1 的这条文档。
GET books/_doc/1
返回结果如下,pageCount 字段的值被设置为了 400,其他字段保持不变。
{
"_index" : "books",
"_id" : "1",
"_version" : 3,
"_seq_no" : 6,
"_primary_term" : 1,
"found" : true,
"_source" : {
"title" : "Cloud Native Patterns",
"isbn" : "9781617294297",
"category" : "Cloud Native",
"pageCount" : 400
}
}
Elasticsearch 还支持通过脚本的方式更新字段,通过编写脚本可以实现更加复杂的处理逻辑。下面命令表示,当 pageCount 字段的值大于 200 时,将 pageCount 的值加 200,否则将 pageCount 的值设置为 99。
POST books/_update/1
{
"script": {
"source": """
if(ctx._source.pageCount > 200) {
ctx._source.pageCount += 200;
}else {
ctx._source.pageCount = 99;
}
"""
}
}
返回结果如下,由于 pageCount 原本的值 400 大于 200,因此 pageCount 的值被更新为了 600(400+200)。
{
"_index" : "books",
"_id" : "1",
"_version" : 4,
"_seq_no" : 7,
"_primary_term" : 1,
"found" : true,
"_source" : {
"title" : "Cloud Native Patterns",
"isbn" : "9781617294297",
"category" : "Cloud Native",
"pageCount" : 600
}
}
除了单条更新文档以外,我们还可以使用 Update By Query API 来根据查询条件批量更新文档。执行以下命令,为 pageCount 小于 400 的书籍添加一个新的字段 description,设置值为 quickStart。
POST books/_update_by_query
{
"query": {
"range": {
"pageCount": {
"lte": 400
}
}
},
"script": {
"source": "ctx._source.description = 'quickStart'"
}
}
不论是关系型数据库,还是 Elasticsearch,只要有数据更新,并发控制是 永恒的话题。在 Elasticsearch 中,数据的更新基于版本进行乐观锁并发控制。在 Elasticsearch 6.7 版本之后推荐使用 _seq_no 和 _primary_term 两个参数进行并发控制。
先获取当前索引的 _seq_no 和 _primary_term 的值。
GET books/_doc/1
返回结果如下。
{
"_index" : "books",
"_id" : "1",
"_version" : 4,
"_seq_no" : 9,
"_primary_term" : 1,
"found" : true,
"_source" : {
"pageCount" : 400,
"isbn" : "9781617294297",
"description" : "quickStart",
"title" : "Cloud Native Patterns",
"category" : "Cloud Native"
}
}
更新文 档时指定 _seq_no 和 _primary_term。
PUT books/_doc/1?if_seq_no=9&if_primary_term=1
{
"doc": {
"pageCount": 500
}
}
返回结果如下,提示更新成功。
{
"_index" : "books",
"_id" : "1",
"_version" : 5,
"result" : "updated",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 10,
"_primary_term" : 1
}
如果指定的 _seq_no 和 _primary_term 不等于当前更新的文档中的值,那么更新将会失败。
PUT books/_doc/1?if_seq_no=9&if_primary_term=1
{
"doc": {
"pageCount": 500
}
}
返回结果如下,提示版本冲突,当前文档 _seq_no 的值已经更新为 10 了,但是还使用老版本 _seq_no 的值 9 来更新。
{
"error" : {
"root_cause" : [
{
"type" : "version_conflict_engine_exception",
"reason" : "[1]: version conflict, required seqNo [9], primary term [1]. current document has seqNo [10] and primary term [1]",
"index_uuid" : "3bYmNTQpRyqOmcwUG1HvNg",
"shard" : "0",
"index" : "books"
}
],
"type" : "version_conflict_engine_exception",
"reason" : "[1]: version conflict, required seqNo [9], primary term [1]. current document has seqNo [10] and primary term [1]",
"index_uuid" : "3bYmNTQpRyqOmcwUG1HvNg",
"shard" : "0",
"index" : "books"
},
"status" : 409
}
8 删除文档
本小节将指导您如何删除 Elasticsearch 中的数据。
使用 DELETE <index-name>/_doc/<doc-id>
语法可以删除索引中指定 doc id 的文档。执行以下命令,删除 doc id 为 1 的文档。
DELETE books/_doc/1
除了单条更新文档以外,我们还可以使用 Delete By Query API 来根据查询条件批量删除文档。执行以下命令,删除所有 pageCount 小于等于 400 的文档。
POST books/_delete_by_query
{
"query": {
"range": {
"pageCount": {
"lte": 400
}
}
}
}