ES_之_操作文档
前言
Github:https://github.com/HealerJean
1、读写文档
Elasticsearch
中的每个索引都分为多个分片,每个分片可以有 多个副本,这些副本称为复制组注意:在添加或删除文档时必须保持同 步。如果不这样做,将导致从一个副本中读取的数据与从另一个副本 中读取的数据表现出截然不同的结果。保持主分片和副本间
复制模型:两两副 本间的数据同步并提供读取服务的过程,我们称之为数据复制模型。
下图展示了复制组的具体含义,此复制组有三个分片,加粗的是主分片,其他两个是副本,这三个分片的数据必须保持一致
1.1、主备模型
Elasticsearch
的数据复制模型是基于主备 (primary
-backup
) 模型的,这个模型在微软研究中心的Pacifica
论文中有很好的描述。 该模型基于复制组中作为主分片的单个数据分片。意思是,假设一个 索引有3个分片、2个副本,那么每个子索引共有3个分片,其中一个 是主分片,两个是副本,为了便于描述主分片,我们称主分片为
primary
,称副本为replica
。primary
用作所有索引操作的主入口点,它负责验证它们并确保它们是正确的。一旦索引操作被primary 接受,primary
还负责将该操作复制到其他replica(分发请求到其他 replica)。另外约定,集群中有若干个节点,其中只有一个是活跃的 主节点,它负载管理集群,我们把它称为master。
1.2、基本写模型
Elasticsearch
中的每个索引操作首先使用路由 (通常基于文档ID
)解析到一个复制组。一旦确定了复制组,该操作将在内部转发到 该组的当前primary
。⬤
primary
负责验证操作并将其转发到其他replica
。由于replica
可以离线,因此不需要primary
复制到所有replica
。⬤ 相反,
Elasticsearch
维护一个应该完成接收操作的replica
列表,此列表称为同步副本组,由主节点维护。顾名思义,这些是一 组“好”的分片拷贝,保证已经处理了所有的索引和删除操作,这些 操作已经被用户确认。primary
负责维护这个不变量,因此必须将所 有操作复制到这个同步副本组中的每个replica
1.3.1、primary
写流程
1、验证传入操作,如果结构无效则拒绝该操作。例如,向一个数 字字段传输一个对象类型。
2、在本地执行操作,即索引或删除相关文档。这还将验证字段的内容,并在需要时拒绝。例如,关键字值对于
Lucene
中的索引而言太长了。3、将操作转发到当前同步副本组中的每个
replica
,如果有多个replica
,这是并行完成的。4、一旦所有
replica
都成功地执行了操作并对primary
作出了响 应,primary
就确认完成了请求并返回给用户。
1.3.2、写流程错误处理
索引数据期间可能会有多种异常情况发生,磁盘可能损坏,节点可能彼此断开,或者某些配置错误可能导致操作在
replica
失败,尽管 在primary
上成功。这种情况虽然不常见,但primary
必须对它们作 出反应。
1、故障转移:如果 primary
本身发生故障,primary
所在的节点将向 master
节点发送相关的消息。索引操作将等待(默认情况下最多1分钟) master
将其中一个 replica
提升为新的 primary
。然后该操作将被转发 到新的 primary
进行处理。同时,master
还监视节点的运行状况,并可能决定主动降级 primary
为 replica
,当包含 primary
的节点由于网络问题与集群隔离时,通常会发生这种情况。
2、副本摘除:一旦在 primary
上成功执行了操作,primary
就必须处理在 ` replica上执行时潜在的故障。这可能是由于
replica上的实际故障或 网络问题导致操作无法到达
replica (或阻止
replica响应)。所有这 些问题会造成相同的最终结果: 作为同步副本组的一部分的
replica会 错过即将被确认的操作。为了避免违反不变量,
primary 向
master 发 送一条消息,请求从同步副本组中删除有问题的
replica。只有在
master 确认清除
replica 后,
primary 才会确认该操作。同时,
master` 还将指示另一个节点开始构建新的副本,以便将系统恢复到健 康状态。
3、主节点下线: 在将操作转发到其他 replica
时,primary
将使用 replica
来验证它是否仍然是活动的 primary
。如果由于网络分区(或GC时间过长)而 隔离了primary
,则在知道到它已降级之前,它可能会继续处理传入的索引操作。来自过时 primary
的操作将被 replica
拒绝,当 primar
y 接收到来自拒绝其请求的 replica
的响应时,它将到达 master
并知道 它已经被替换,然后将操作路由到新的 primary
。
1.3、基本读模型
Elasticsearch
中的读取可以是非常轻量的按ID
查找,也可以是 一个具有复杂聚合的繁重搜索请求,这些聚合需要非常大的CPU
能 力。主备 (primary
-backup
)模型的一个优点是它保持所有的分片 (primary
和replica
)是等同的。因此,单个同步拷贝(称之为相关分片组)就足以满足读取请求。
1.3.1、读流程
当节点接收到读取请求时,该节点负责将其转发到保存相关分片的节点整理响应,并向客户机返回结果。该节点被称为该请求的协调 节点。基本流程如下:
1、将读取请求解析到相关分片组。注意,由于大多数搜索将被发送到一个或多个索引,所以它们通常需要从多个分片中读取,每个分片表示数据的不同子集。
2、从同步副本组中选择一个相关 shard
的活动分片。这可以是 primary
,也可以是 replica
。默认情况下,Elasticsearch
只需在分 片之间循环搜索。
3、向所选分片发送读取请求。
4、将结果整合。请注意,在按 ID
查找的情况下,只有一个分片是 相关的,可以跳过此步骤。
1.3.2、读流程错误处理
当一个分片未能响应读取请求时,协调节点将请求发送到同步副 本组中的另一个分片。重复失败可能导致没有可用的分片。为了确保快速响应,如果一个或多个分片失败,以下
API
将以部分结果响应:
⬤ Search API
⬤ Multi Search
⬤ Bulk
⬤ Multi Get
包含部分结果的响应仍然提供200 OK HTTP状态代码。相关分 片的失败信息记录在响应头部字段里。
2、索引 API
索引操作成功执行时,
successful
至少是1
。说明:默认情况下,当索引操作成功返回时,有可能一些
replica
还没有开始或完成,因为只要primary
成功执行,就会返回,这种行 为可以调整。其实这样做的目的是快速响应,一般的场景并不需要等 待所有分片都完成索引操作再返回,除非对数据安全要求极高的场 景。
key |
说明 |
---|---|
_shards |
头提供有关索引操作的复制过程的信息 |
total |
指示索引操作应在多少个分片 (主 primary 和 replica )上执行 |
successful |
指示索引操作成功执行的分片数 |
failed |
在副本分片上索引操作失败的情况下包含与复制相关的错误的数组。 |
入参:
PUT twitter/_doc/1
{
"user" : "kimchy",
"post_date" : "2009-11-15T14:12:12",
"message" : "trying out Elasticsearch"
}
出参:
{
"_shards" : {
"total" : 2,
"failed" : 0,
"successful" : 2
},
"_index" : "twitter",
"_type" : "_doc",
"_id" : "1",
"_version" : 1,
"_seq_no" : 0,
"_primary_term" : 1,
"result" : "created"
}
2.1、自动创建索引
当索引文档时,如果索引不存在,会自动创建索引。索引操作还 将创建一个动态映射(如果尚未存在)。默认情况下,如果需要,新字段和对象将自动添加到映射定义中。
自动创建索引由
action.auto_create_index
设置控制。1、此设置默 认为
true
,这意味着索引总是自动创建的。2、也可以设置只有匹配特定模式的索引才允许自动创建索引,方法是将此设置的值更改为这些匹配模式的逗号分隔列表。
3、还可以通过在列表中的模式前面加上 + 或 - , 明确地允许和禁止使用它。
4、最后,通过将此设置更改为
false
,可以完 全禁用它。可以在elasticsearch.ym
l 中配置,也可以通过如下URL
配置。下面是几个示例。
2.1.1、特定模式才允许创建
只允许自动创建名为
index
10
的索引,不允许创建其他与index1*
匹配的索引
PUT _cluster/settings
{
"persistent": {
"action.auto_create_index": "twitter,index10,-index1*,+ind*"
}
2.1.2、完全禁用索引的自动创建
PUT _cluster/settings
{
"persistent": {
"action.auto_create_index": "false"
}
2.1.3、允许使用任何名称自动创建索引
是默认设置
PUT _cluster/settings
{
"persistent": {
"action.auto_create_index": "true"
}
2.1.4、索引存在 ( 覆盖&失败 )
索引操作还接受一个
op_type
参数,它可以用来强制create
操 作,允许put-if-absent
的行为。使用create
时,如果索引中已存在具 有该ID
的文档,则索引操作将失败。⬤ 默认情况下,当文 档存在时直接覆盖。
⬤ 当索引文档时,如果带有
&op_type=true
参 数,明确指明是创建文档,如果文档存在就报错。
入参:
PUT twitter/_doc/1?op_type=create
{
"user" : "kimchy",
"post_date" : "2009-11-15T14:12:12",
"message" : "trying out Elasticsearch"
}
出参:
{
"error" : {
"root_cause" : [
{
"type" : "version_conflict_engine_exception",
"reason" : "[1]: version conflict, document already exists (current version [1])",
"index_uuid" : "d9PDPxM-Tja9Hb1k1jsEbA",
"shard" : "0",
"index" : "twitter"
}
],
"type" : "version_conflict_engine_exception",
"reason" : "[1]: version conflict, document already exists (current version [1])",
"index_uuid" : "d9PDPxM-Tja9Hb1k1jsEbA",
"shard" : "0",
"index" : "twitter"
},
"status" : 409
}
2.2、ID
自动生成
索引操作可以在不指定
ID
的情况下执行。在这种情况下,将自动 生成一个ID
。此外,op_type
将自动设置为create
。下面是一个例子 (注意使用POST
而不是PUT
)
2.3、路由
默认情况下,碎片放置(或路由)是通过使用文档
id
值的散列来控制的。为了实现更明确的控制,可以使用路由参数直接在每个操作的基础上指定路由器使用的散列函数的值。注意:在设置显式
mapping
时,可以选择使用routing
字段从文档本身 提取路由值。如果定义了mapping
的_routing
值并将其设置为必需, 则如果没有提供可提取路由值,索引操作将失败。
POST /twitter/_doc?routing=kimchy
{
"user" : "kimchy",
"post_date" : "2009-11-15T14:12:12",
"message" : "trying out Elasticsearch"
}
2.4、分发
索引操作根据路由定向到
primary
,并在包含此分片的实际节点 上执行。在primary
完成操作后,如果需要,操作将分发到需要的其他分片。
2.5、等待活动分片
为了兼顾系统写入的效率和可靠性,可以将索引操作配置为在继 续操作之前等待一定数量的活动分片。如果所需数量的活动分片不可用,则写入操作必须等待并重试,直到所需分片已启动或发生超时。 默认情况下,写入操作仅在继续之前等待
primary
完成 (即wait_for_active_shards
=1
) 。1、可以通过设置
index.write.wait_for_active_shards
来 动 态 重 写 此 默 认 值 。2、要 更 改 每个请求操作的此行为,可以使用
wait_for_active_shards
请求参 数。wait_for_active_shards
的有效值是任何正整数,最多为分片总 数。指定负值或大于分片数的数字将引发错误。
例如:假设有一个由 3
个节点 ( A
、B
和 C
) 组成的集群,并且创 建了一个索引 index
,其中副本数设置为 3
(结果是共 4
个分片(但是实际上不存在4个分配))。 如果我们尝试索引操作
1、默认情况下,该操作将仅确保 primary
在继续操作之前可用。这意味着,即使 B
和 C
发生故障,并且 A
托管了 primary
, 索 引 操 作 仍 然 继 续 进 行 。
2、如果在请求中将 wait_for_active_shards
设置为 3
( 并且所有 3
个节点都已启动),那么索引操作将需要3个活动的 shard
副本才能继续。这一要求应该满足,因为集群中有 3
个活动的节点,每个节点都保存一个 shard
副本。 但是,如果我们将 wait_for_active_shards
设置为 all
( 或设置为 41
, 这是相同的),则索引操作将不会继续,因为索引中没有每个 shard
的所有4个副本。除非在集群中出现新节点以承载分片的第四副本, 否则操作将超时
2.6、detect_noop
参数
使用索引
API
更新文档时,即使文档没有更改,也会始终创建文档的新版本。如果不想这样做,可以使用detect_noop
=true
参数。这 个参数的作用是在更新之前与原文档对比,如果没有字段值的变化, 则不做更新操作。
3、GET
API
3.1、根据id
查询索引文档
GET API
允许根据其ID
从索引中获取JSON
文档。以下示例从ID
值为1
的JSON
文档:
入参:
GET twitter/_doc/1
出参:
{
"_index" : "twitter",
"_id" : "1",
"_version" : 1,
"_seq_no" : 0,
"_primary_term" : 1,
"found" : true,
"_source" : {
"user" : "kimchy",
"post_date" : "2009-11-15T14:12:12",
"message" : "trying out Elasticsearch"
}
}
3.2、head
检查文档是否存在
3.2.1、不存在
入参:
HEAD twitter/_doc/0
出参:
{
"statusCode": 404,
"error": "Not Found",
"message": "404 - Not Found"
}
3.2.2、存在
入参:
HEAD twitter/_doc/1
出参:
200 - OK
3.3、实时性
默认情况下,
GET
API
是实时的,不受索引刷新频率的影响。如果文档已更新但尚未刷新,则GET
API
将在适当时机发出刷新调用, 以使文档可见。这还将使上次刷新后更改的其他文档可见。如果需要禁用此特性,可以将realtime
参数设置为false
。
3.4、字段选择
3.4.1、_source_includes
和 _source_excludes
如果只需要完整
_source
中的一个或两个字段,可以使用_source_includes
和_source_excludes
参数来包含或排除字段。这 对于大型文档尤其有用,因为部分字段检索可以节省网络开销。两个参数都采用逗号分隔的字段列表或通配符表达式。
入参:
GET twitter/_doc/1?_source_includes=*.date&_source_excludes=entities
3.4.2、_source
如果只需指定
include
,可以使用较短的表示法:
入参:
GET twitter/_doc/1?_source=*.id,retweeted
3.5、直接获取_source
可以使用
/{index}/_source/{id}
仅获取文档的 `source 字段,而不 返回任何其他内容,用法如下:
3.5.1、只返回 _source
入参:
GET twitter/_source/1
出参:
{
"counter" : 1,
"tags" : [
"red"
]
}
3.5.2、筛选 _source
字段
入参:
GET twitter/_source/1/?_source_includes=*&_source_excludes=entities
出参:
{
"counter" : 1,
"tags" : [
"red"
]
}
3.5.3、检查 _source
是否存在
入参:
HEAD twitter/_source/1
出参:
200 - OK
3.6、routing
路由
如果在索引文档时使用了路由参数,搜索时也应该加上该参数。 当然搜索时不加也是可以的,这会降低性能。如下示例,指定了路 由:
GET twitter/_doc/2?routing=user1
3.7、preference
参数
preference
参数的作用是控制优先从哪个shard
获取数据。默认 情况下是随机选择的。一般情况下可以设置为_local
,这可以降低网 络开销。⬤
local
:如果可能,该操作将更倾向于在本地分配的分片上执行。⬤
Custom (string) value
: 自定义值将用于保证相同的分片将用于相同的自定义值。 当在不同的刷新状态下击中不同的分片时,这有助于“跳跃值”。 示例值可以是Web
会话 ID 或用户名之类的东西。
3.8、refresh
参数
可以将
refresh
参数设置为true
,以便在GET
操作之前刷新相关 的分片并使其可见。将其设置为true
应慎重考虑,因为这可能导致系 统负载过重,并减慢索引速度。
3.9、分发
GET
操作被散列到一个特定的分片ID
上,然后被重定向到该分片ID
对应的一个副本,并返回结果。副本是主分片及其在该分片ID
上的 副本。这意味着拥有的副本越多,将拥有更好的扩展能力
1.10、存储字段
GET
操作允许指定一组存储字段 (store
属性值为true
),这些 字段将通过传递stored_fields
参数返回。如果未存储请求的字段,则 将忽略它们。例如,首先建立以下映射
入参:
PUT twitter
{
"mappings": {
"properties": {
"counter": {
"type": "integer",
"store": false
},
"tags": {
"type": "keyword",
"store": true
}
}
}
}
PUT twitter/_doc/1
{
"counter" : 1,
"tags" : ["red"]
}
1.10.1、检索数据
入参:
GET twitter/_doc/1?stored_fields=tags,counter
出参:
{
"_index" : "twitter",
"_id" : "1",
"_version" : 1,
"_seq_no" : 0,
"_primary_term" : 1,
"found" : true,
"fields" : {
"tags" : [
"red"
]
}
}
4、删除 API
4.1、根据特定文档 Id
删除
删除
API
(DELETE
) 允许根据特定文档的ID
从其中删除JSON
文档。下面的示例将ID
为1的JSON
文档从
入参:
DELETE /twitter/_doc/1
出参:
{
"_index" : "twitter",
"_id" : "1",
"_version" : 2,
"result" : "deleted",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 1,
"_primary_term" : 1
}
4.2、查询删除
4.2.1、查询匹配并删除
查询删除
API
(_delete_by_query
)是对每个与查询匹配的文档 执行删除操作。删除过程:
_delete_by_query
操作在启动时会获取索引的一个快照,并使用 内部版本控制删除找到的内容。这意味着,如果文档在获取快照的时 间和处理删除请求的时间之间发生更改,则会出现版本冲突。当版本匹配时,文档将被删除。具体过程:
1、在
_delete_by_query
执行期间,将按顺序执行多个搜索请求,以查找所有要删除的匹配文档。每当找到一批文档时,都会执行相应的 批量请求来删除所有这些文档。2、如果搜索或批量请求被拒绝,
_delete_by_query
按照默认策略重试被拒绝的请求(最多10次,指数 下降)。达到最大重试次数限制会导致_delete_by_query
中止,并在响应的failures中返回所有失败信息。3、已执行的删除操作仍然保持不 变。换句话说,操作不会回滚,只会中止。
4、当第一个失败导致中止时,由失败的批量请求返回的所有失败信息都会
在failures
元素中返 回,因此,可能会有相当多失败的实体。
4.2.1.1、简单的查询删除
入参:
POST twitter/_delete_by_query
{
"query": {
"match": {
"name": "HealerJean"
}
}
}
出参:
{
"took" : 34,
"timed_out" : false,
"total" : 1,
"deleted" : 1,
"batches" : 1,
"version_conflicts" : 0,
"noops" : 0,
"retries" : {
"bulk" : 0,
"search" : 0
},
"throttled_millis" : 0,
"requests_per_second" : -1.0,
"throttled_until_millis" : 0,
"failures" : [ ]
}
4.2.1.2、拒绝版本冲突中止
如果不想因版本冲突而让它们中止,那么在
URL
上设置conflicts
=proceed
或在请求正文中设置conflicts:proceed
举例:从 twitter
索引中删除 tweet
入参:
POST twitter/_delete_by_query?conflicts=proceed
{
"query": {
"match_all": {}
}
}
4,2.1.3、一次删除多个索引文档
入参:
POST twitter,blog/_delete_by_query
{
"query": {
"match_all": {}
}
}
4,2.1.4、routing
路由
如果提供了
routing
,则路由将复制到滚动(scroll
) 查询中,并 将操作限制在与该路由值匹配的分片上,如下示例:
入参:
POST twitter/_delete_by_query?routing=1
{
"query": {
"range" : {
"age" : {
"gte" : 10
}
}
}
}
4,2.1.5、scroll_size
滚动批次
默认情况下,
_delete_by_query
查询使用的滚动批次大小为 1000。可以使用scroll_size
参数更改批次大小
入参:
POST twitter/_delete_by_query?scroll_size=5000
{
"query": {
"term": {
"user": "kimchy"
}
}
}
4.2.2、URL
参数
除了标准参数 ( 如
pretty
) 外,_delete_by_query
API
还支持refresh
、wait_for_completion
、wait_for_active_shards
、timeout
和scrol
l。
4.2.2.1、refresh
发送带有
refresh
参数的请求,将在请求完成后刷新涉及的所有分片。这与DELETE
API
的refresh
参数不同,后者只会刷新接收到删除请求的分片。同时,它不支持wait_for
参数。
4.2.2.2、wait_for_completion
如 果 请 求 包 含
wait_for_completion
=false
设 置 , 那 么Elasticsearch
将执行一些预检查。启动请求,然后返回一个Task
以取消或获取任务的 状 态 。
Elasticsearch
还 将 在.tasks/task/${taskId}
索引中创建此任务的记录文档,用户可以根 据需要保留或删除创建的文档,完成后删除它。这样Elasticsearch
可以回收它使用的空间。
4.2.2.3、wait_for_active_shards
& timeout
⬤
wait_for_active_shards
参数用来控制在继续执行请求之前必须激活多少个分片或副本。⬤
timeout
参数用来控制每个写请求等待不可用分片变为可用的时间。这两个参数在批量
API
中的工作方式完全相 同。由于_delete_by_query
使用scroll
搜索,还可以指定scroll
参数 来控制“搜索上下文”保持活动的时间,例如scroll
=10m
。默认为5
分钟。
4.2.24、requests_per_second
requests_per_second
参数可以设置为任何正十进制数(1.4、 6、1000等),并通过用等待时间填充每个批来限制通过查询发出删 除操作批的速率。通过将requests_per_second
设置为-1,可以禁用 限制。此限制是通过在批之间等待来完成的,这样就可以为 ` _delete_by_query
内部使用的滚动指定一个超时时间。这个时间是批 处理大小除以
requests_per_second与写入时间之差。默认情况下, 批处理大小为
1000,因此如果
requests_per_second设置为
500` ,计算方式如下:
target_time = 1000/500 per second=2 seconds
wait_time = target_time - write_time = 2 seconds-.5seconds = 1.5 seconds
注意:由于该操作是作为单个 _bulk
请求发出的,因此较大的批大小将 导致 Elasticsearch
创建多个请求,并在启动下一个操作之前等待一 段时间,这是不平稳的。默认值为-1。
4.2.3、返回体
{
"took": 147,
"timed_out": false,
"total": 119,
"deleted": 119,
"batches": 1,
"version_conflicts": 0,
"noops": 0,
"retries": {
"bulk": 0,
"search": 0
},
"throttled_millis": 0,
"requests_per_second": -1,
"throttled_until_millis": 0,
"failures": []
}
key |
说明 |
---|---|
took |
整个操作从开始到结束的毫秒数。 |
timed_out |
如果在执行_delete_by_query期间执行的任何 请求超时,则此标志为true |
total |
成功处理的文档数 |
deleted |
成功删除的文档数 |
batches |
分了多少批次执行 |
version_conflicts |
版本冲突的文档数。 |
noops |
对于_delete_by_query,此字段始终等于零。 |
retries |
操作尝试的重试次数。 |
bulk |
重试的批量操作数, |
search |
重试的搜索操作数。 |
throttled_millis |
请求休眠以符合 requests_per_second 参数设置的毫秒数。 |
requests_per_second |
每秒有效执行的请求数 |
throttled_until_millis |
在_delete_by_query 响应中,此字段应始终等于零。它只有在使用 _tasks API 时才有意义,在 该 API 中,它指示下一次将再次执行请求的等待时间(从 epoch 开始以毫秒为单位)。 |
failures |
⬤ 如果请求处理中有任何不可恢复的错误,则记录 到这个失败数组中。如果不为空,那么请求会因为这些失败 而中止。 ⬤ _delete_by_query 是使用批处理实现的,任何失败 都会导致整个过程中止,但当前批处理中的所有失败都会收 集到此数组中。可以使用conflicts选项防止覆盖写入在版本 冲突时中止。 |
4.2.4、任务 API
可 以 使 用 任 务
API
( ` _tasks ` ) 获 取 任 何 正 在 运 行 的_delete_by_query
的状态:
入参:
GET _tasks?detailed=true&actions=*/delete/byquery
解析:返回结果中的 status
字段,包含任务的实际状态。 total
字段 是重新索引预期执行的操作总数。可以通过updated
、 created
和 deleted
的字段的加总值来估计进度。当它们的总和等于合计字段时, 请求将完成。
出参:
{
"nodes": {
"r1A2WoRbTwKZ516z6NEs5A": {
"name": "r1A2WoR",
"transport_address": "127.0.0.1:9300",
"host": "127.0.0.1",
"ip": "127.0.0.1:9300",
"attributes": {
"testattr": "test",
"portsfile": "true"
},
"tasks": {
"r1A2WoRbTwKZ516z6NEs5A:36619": {
"node": "r1A2WoRbTwKZ516z6NEs5A",
"id": 36619,
"type": "transport",
"action": "indices:data/write/delete/byquery",
"status": {
"total": 6154,
"updated": 0,
"created": 0,
"deleted": 3500,
"batches": 36,
"version_conflicts": 0,
"noops": 0,
"retries": 0,
"throttled_millis": 0
},
"description": ""
}
}
}
}
}
4.2.4.1、使用任务ID
,可以直接查找任务:
此
API
的优点是,它可以与wait_for_completion
=false
一起使 用,以透明地返回已完成任务的状态。如果任务已完成,并且在其上设置了
wait_for_completion
=false
,那么它将返回results
或error
字 段。此功能的成本是创建的新的文档,需要手动来删除创建的文档。
入参:
GET /_tasks/r1A2WoRbTwKZ516z6NEs5A:36619
4.2.5、取消任务 API
可以使用取消任务
API
(_cancel
) 取消_delete_by_query
进程:可以使用任务
API
找到任务ID。取消应该很快发生,但可能需要几秒钟。上面的任务状态API
将 继续列出相应的任务,直到该任务检查它是否已被取消并自行终止。
入参:
POST_tasks/r1A2WoRbTwKZ516z6NEs5A:36619/_cancel
4.2.6、动态调整 API
requests_per_second
的 值 可 以 在 运 行 时 使 用 动 态 调 整API
(_rethrottle
)进行更改:1、可以使用任务API找到任务ID。就像在
_delete_by_query
API
上设置它一样,requests_per_second
可以置为-1以禁用限制,也可以是任何十进制数(如1.7或12)以限制到该级别。2、加快查询速度的重新标记将立即 生效,但减慢查询速度的重新标记将在完成当前批处理后生效。这样可以防止滚动超时。
入参:
POST _delete_by_query/r1A2WoRbTwKZ516z6NEs5A:36619/_rethrottle?requests_per_second=-1
4.2.7、切片
_delete_by_query
API
支持切片滚动,使删除过程并行。这种并行化可以提高效率,并提供一种方便的方法将请求分解为较小的部 分。
4.2.7.1、人工切片
通过为每个请求提供一个切片
ID
和切片总数,进行人工切片:
入参:
POST twitter/_update_by_query
{
"slice": {
"id": 0,
"max": 2
},
"script": {
"source": "ctx._source['extra'] = 'test'"
}
}
POST twitter/_update_by_query
{
"slice": {
"id": 1,
"max": 2
},
"script": {
"source": "ctx._source['extra'] = 'test'"
}
}
验证是否生效,入参:
GET _refresh
POST twitter/_search?size=0&q=extra:test&filter_path=hits.total
4.2.7.2、自动切片
可以让
_delete_by_query
过程自动并行化,方法是使用“切片滚 动”机制对_id
进行切片1、使用
slices
指 定要使用的切片数,把slices
设置为auto
将允许Elasticsearch
选择要使用的切片数。 此设置将会为每个分片使用一个切片,直至达到某个限制。2、如果存在多个源索引,它将根据具有最小分片数的索引选择切片数。通过在
_delete_by_query
API
中添加slices
会自动执行切片过 程。
入参:
POST twitter/_update_by_query?refresh&slices=5
{
"script": {
"source": "ctx._source['extra'] = 'test'"
}
}
验证是否生效,入参:
POST twitter/_search?size=0&q=extra:test&filter_path=hits.total
4.2.7.3、切片数量选择
⬤ 如果使用自动切片机制,将为大多数索引选择一个合理的切片数字。
⬤ 如果要手动切片或调整自动切片,请遵循以下准则:
1、当切片数等于索引中的分片数时,查询性能最佳。如果该数字很大(例如500),请选择一个较小的数字,因为太多的切片会影响性能。设置高于分片数量的切片通常不会提高效 率并增加开销。
2、 删除性能随可用资源的切片数线性扩展。
3、查询或删除性能是否支配运行时间取决于重新索引的文档和 集群资源。
5、更新 API
5.1、使用 script
更新
5.2、部分字段更新
更新
API
还支持传递部分文档字段进行更新,在内部完成合并 (简单的递归合并、对象的内部合并、替换核心“键值”和数组)。 要完全替换现有文档,应使用索引API
。以下实例,通过部分更新机 制将现有文档添加新字段:注意:如果同时指定了
doc
和script
,则忽略doc
。
入参:
POST /animal/_update/1?pretty
{
"doc": {
"name": "熊猫update"
}
}
5.3、避免无效更新
⬤ 如果指定了
doc
,则其值将与现有的_source
合并。默认情况下, 不更改任何内容的更新并不会真正执行并返回 “result
“: “noop
”⬤ 因为传入的
name
值和source
中的一样,则忽略整个更新请求。 如果请求被忽略,响应中的result
元素将返回noop
。
入参:
POST /animal/_update/1?pretty
{
"doc": {
"name": "熊猫update"
}
}
出参:
{
"_index" : "animal",
"_id" : "1",
"_version" : 17,
"result" : "noop",
"_shards" : {
"total" : 0,
"successful" : 0,
"failed" : 0
},
"_seq_no" : 33,
"_primary_term" : 3
}
5.4、upsert
元素
如果文档不存在,则
upsert
元素的内容将作为新文档插入。如果 文档确实存在,则将执行script:
5.4.1、文档不存在,则创建
入参:
POST test/_update/2
{
"script" : {
"inline": "ctx._source.counter += params.count",
"lang": "painless",
"params" : {
"count" : 4
}
},
"upsert" : {
"counter" : 1
}
}
出参:
解析:因为ID为2的文档不存在,可以看出执行了创建操作 (“result”:”created”)。
{
"_index" : "test",
"_id" : "2",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 0,
"_primary_term" : 1
}
5.4.2、文档存在,则执行 Script
入参:
POST test/_update/2
{
"script" : {
"inline": "ctx._source.counter += params.count",
"lang": "painless",
"params" : {
"count" : 4
}
},
"upsert" : {
"counter" : 1
}
}
出参:
{
"_index" : "test",
"_id" : "2",
"_version" : 4,
"result" : "updated",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 3,
"_primary_term" : 1
}
5.5、查询更新
查询更新
API
(_update_by_query
) 的功能是在不更改源的情况 下对索引中的每个文档执行更新。这对于获取新属性或其他联机映射 更改很有用。示例如下:
查询更新过程:
1、_update_by_query
在索引启动时获取索引的快照,并使用 internal
版本控制索引它。这意味着如果文档在拍摄快照的时间和处理索引请求之间发生更改,则会出现版本冲突。当版本匹配时,文档会更新,版本号会递增。
2、所有更新和查询失败都会导致 _update_by_query
中止并 failures
在响应中返回。已执行的更新仍然存在。换句话说,该过程不会回滚,只会中止。
4、当第一个失败导致中止时,失败的批量请求返回的所有失败都将在failures
元素中返回; 因此,可能存在相当多的失败实体。
5、如果您只想计算版本冲突,不要导致_update_by_query
中止,您可以 conflicts
=
proceed
在 URL
或 "conflicts": "proceed"
请求正文中设置。
5.5.1、URL
参数
除了标准的参数,如
pretty
,此更新通过查询API也支持refresh
,wait_for_completion
,wait_for_active_shards
,timeout
和scroll
。
5.5.1.1、refresh
发送将在请求完成时更新正在更新的索引中的所有分片。这与
Index
API
的refresh
参数不同,后者仅导致接收新数据的分片被编入索引。
5.5.1.2、wait_for_completion
如果请求包含
wait_for_completion
=false
,那么Elasticsearch
将执行一些预检查,启动请求,然后返回一个Task
,以取消或获取任务的状态。Elasticsearch
还将在.asks
/task
/${taskId}
. 索引中创建此任务的记录文档,可以根据需要保留或删除创建的文档。完成后 删除它,这样Elasticsearch
可以回收它使用的空间。
5.5.1.3、wait_for_active_shards
& timeout
⬤
wait_for_active_shards
控制在继续执行请求之前必须激活多少 个shard
副本。⬤
timeout
控制每个写请求等待不可用分片变为可用分片的时间。这两个参数在
Bulk
API
中的工作方式完全相同。由于_update_by_query
操作使用滚动搜索,还可以指定scroll
参数来控制 “搜索上下文”保持活动的时间,例如scroll
=10m
。默认为5分钟。
5.5.1.4、requests_per_second
requests_per_second
可以被设置为任何正十进制数(1.4
,6
,1000
等)和节流速率_update_by_query
通过填充每个批次由一等待时间发出索引操作的批次。可以通过设置requests_per_second
为禁用限制-1
。
通过在批处理之间等待来完成限制,以便在_update_by_query
内部使用的滚动 可以被赋予考虑填充的超时。填充时间是批量大小除以requests_per_second
写入所花费的时间之间的差异。默认情况下,批处理大小为 1000
,因此如果requests_per_second
设置为500
:
target_time = 1000 / 500 per second = 2 seconds
wait_time = target_time - delete_time = 2 seconds - .5 seconds = 1.5 seconds
5.5.2、请求体
JSON
响应如下
{
"took" : 147,
"timed_out": false,
"total": 5,
"updated": 5,
"deleted": 0,
"batches": 1,
"version_conflicts": 0,
"noops": 0,
"retries": {
"bulk": 0,
"search": 0
},
"throttled_millis": 0,
"requests_per_second": -1.0,
"throttled_until_millis": 0,
"failures" : [ ]
}:
· :
· :。 · :。 · :。 · :。 · :。 · :。
· :。bulk是重试的批量操作数, search是重试的搜索操作数。
| key | 说明 |
| ———————— | ———————————————————— |
| took
| 整个操作从开始到结束的毫秒数。 |
| timed_out
| 如果在操作执行期间的任何请求超时,则此标 志设置为true。 |
| total
| 成功处理的文档数 |
| updated
| 成功更新的文档数 |
| deleted
| 成功删除的文档数 |
|
batches | 分了多少批次执行 |
|
version_conflicts | 版本冲突的文档数 |
|
noops | 当设置了ctx.op="noop"时被忽略的文档数 |
|
retries | 尝试的重试次数 |
|
bulk | 是重试的批量操作数 |
|
search | 是重试的搜索操作数 |
|
throttled_millis | 请求 眠 以 符 合 requests_per_second 的毫秒数。 |
|
requests_per_second | 每秒有效执行的请求数。 |
|
throttled_until_millis | 在
_update_by_query 响应中,此 字段应始终等于零。<br>只有在使用
TASK AP I时才有意义, 在该
API 中,它指示下一次将再次执行请求的等待时间(从 epoch开始以毫秒为单位),以符合
requests_per_second 参数的限制要求 |
|
failures | ⬤ 如果请求处理中有任何不可恢复的错误,则记录 到这个失败数组中。如果这不是空的,那么请求会因为这些失败而中止。
_update_by_query 是使用批处理实现的,任 何失败都会导致整个过程中止><br/>⬤ 但当前批处理中的所有失败 信息都会收集到数组中。可以使用conflicts
选项防止操作在 版本冲突时中止。 |
5.5.3、任务API
同查询删除 任务API
5.5.4、取消任务API
同查询删除 取消任务API
5.5.5、动态调整API
同查询删除 动态调整API
5.5.6、切片
同查询删除 动态调整API
6、MGet
API
MGet
API
(_mget
) 基于单个索引、类型(可选)和ID
(可能 还有路由)返回多个文档。响应包括一个doc
s数组,其中包含与原始 ` _mget请求相对应的所有已提取文档(如果特定
Get失败,则在响应 中包含此错误的对象)。成功的
Get的结构与
GetAP`I提供的文档在结 构上类似。示例如下:
6.1、普通查询
入参:
GET _mget
{
"docs": [
{
"_index": "example",
"_id": "1"
},
{
"_index": "example",
"_id": "2"
},
{
"_index": "example_test",
"_id": "1"
},
{
"_index": "example_test",
"_id": "2"
}
]
}
6.2、指定索引查询
_mget
请求也可以用于指定索引(在这种情况下,主体中不需要 它)
入参:
GET test/_doc/_mget
{
"docs": [
{
"_id": "1"
},
{
"_id": "2"
},
{
"_id": "1"
},
{
"_id": "2"
}
]
}
6.2.1、简化查询
可以直接使用
ids
元素来简化请求:
入参:
GET test/_mget
{
"ids": ["1", "2"]
}
6.3、_source
过滤
默认情况下,将为每个文档返回_source字段(如果已存储)。 与
Get
API
类似,可以使用_source
参数仅检索_source
的部分内容 ( 或 者 根 本 不 检 索 ) , 还 可 以 使 用URL
参 数_source
、_source_includes
和_source_excludes
指定默认值。示例如下:
入参:
GET /_mget
{
"docs" : [
{
"_index" : "test",
"_id" : "1",
"_source" : false
},
{
"_index" : "test",
"_id" : "2",
"_source" : ["field3", "field4"]
},
{
"_index" : "test",
"_id" : "3",
"_source" : {
"include": ["user"],
"exclude": ["user.location"]
}
}
]
}
6.4、存储字段
可以为每个要获取的文档指定检索特定存储字段(
store
属性为true
),类似于Get
API
的stored_fields
参数。例如:
6.4.1、请求体指定
入参:
GET /_mget
{
"docs" : [
{
"_index" : "test",
"_id" : "1",
"stored_fields" : ["field1", "field2"]
},
{
"_index" : "test",
"_id" : "2",
"stored_fields" : ["field3", "field4"]
}
]
}
6.4.2、URL
中指定
可以在查询字符串中指定
stored_fields
参数作为默认值, 应用于所有文档
入参:
GET /test/_doc/_mget?stored_fields=field1,field2
{
"docs" : [
{
"_id" : "1"
},
{
"_id" : "2",
"stored_fields" : ["field3", "field4"]
}
]
}
6.5、路由
可以将路由值作为参数
举例:
1、文档 test/_doc/2
将从路由键key1
对应的分片中获取,
2、文档 test/_doc/1
将从路由键 key2
对应的分片中提取,因为 test/_doc/2
没有单独指定路由。
入参:
GET /_mget?routing=key1
{
"docs" : [
{
"_index" : "test",
"_id" : "1",
"routing" : "key2"
},
{
"_index" : "test",
"_id" : "2"
}
]
}
7、bulk
批量操作
批量操作
API
(_bulk
) 可以在单个API
调用中执行多个索引和删 除操作。这可以大大提高索引速度⬤
bulk
api
对json
的语法,有严格的要求,每个json
串不能换行,只能放一行,同时一个json
串和一个json
串之间,必须有一个换行⬤
bulk
操作中,任意一个操作失败,是不会影响其他的操作的,但是在返回结果里,会告诉你异常日志⬤
bulk size
最佳大小:bulk
request
会加载到内存里,如果太大的话,性能反而会下降,因此需要反复尝试一个最佳的bulk
size
-。一般从1000-5000条数据开始,尝试逐渐增加。另外,如果看大小的话,最好是在5-15MB
之间。
7.1、简单操作
入参:
POST _bulk
{"delete":{"_index":"megacorp","_id":30}}
{"create":{"_index":"megacorp","_id":5}}
{"first_name":"John","last_name":"Smith","age":25,"about":"I love to go rock climbing","interests":["sports","music"]}
{"create":{"_index":"megacorp","_id":6}}
{"first_name":"John","last_name":"Smith","age":25,"about":"I love to go rock climbing","interests":["sports","music"]}
{"index":{"_index":"megacorp","_id":7}}
{"first_name":"John","last_name":"Smith","age":25,"about":"I love to go rock climbing","interests":["sports","music"]}
{"index":{"_index":"megacorp","_id":8}}
{"first_name":"John","last_name":"Smith","age":25,"about":"I love to go rock climbing","interests":["sports","music"]}
{"update":{"_index":"megacorp","_id":1}}
{"doc":{"age":55}}
出参:
{
"took" : 29,
"errors" : true,
"items" : [
{
"delete" : {
"_index" : "megacorp",
"_id" : "30",
"_version" : 1,
"result" : "not_found",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 5,
"_primary_term" : 1,
"status" : 404
}
},
{
"create" : {
"_index" : "megacorp",
"_id" : "5",
"status" : 409,
"error" : {
"type" : "version_conflict_engine_exception",
"reason" : "[5]: version conflict, document already exists (current version [1])",
"index_uuid" : "n8I5TI3SQDuVuFoLuPxvnw",
"shard" : "0",
"index" : "megacorp"
}
}
},
{
"create" : {
"_index" : "megacorp",
"_id" : "6",
"status" : 409,
"error" : {
"type" : "version_conflict_engine_exception",
"reason" : "[6]: version conflict, document already exists (current version [1])",
"index_uuid" : "n8I5TI3SQDuVuFoLuPxvnw",
"shard" : "0",
"index" : "megacorp"
}
}
},
{
"index" : {
"_index" : "megacorp",
"_id" : "7",
"_version" : 2,
"result" : "updated",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 6,
"_primary_term" : 1,
"status" : 200
}
},
{
"index" : {
"_index" : "megacorp",
"_id" : "8",
"_version" : 2,
"result" : "updated",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 7,
"_primary_term" : 1,
"status" : 200
}
},
{
"update" : {
"_index" : "megacorp",
"_id" : "1",
"status" : 404,
"error" : {
"type" : "document_missing_exception",
"reason" : "[1]: document missing",
"index_uuid" : "n8I5TI3SQDuVuFoLuPxvnw",
"shard" : "0",
"index" : "megacorp"
}
}
}
]
}
7.2、指定索引操作
如果只是操作同一个索引可以想
mget
一样指定索引
入参:
POST /megacorp/_bulk
{"delete":{"_id":30}}
{"delete":{"_id":31}}
{"delete":{"_id":32}}
7.3、路由
每个批量项目都可以使用
routing
字段传递路由值。它会根据 _routing映射自动跟踪索引和删除操作的行为。
7.4、批量更新
当使用更新操作时,
retry_on_conflict
可以用作操作本身(不在额外的有效负载行中)中的字段,以指定在发生版本冲突时应重试更 新的次数。
Update
操作支持以下选项 :doc
(部分文档)、upsert
、doc_as_upsert
、script
、params
用于脚本)、lang(
用于脚本) 和_source
。更新操作示例如下:
POST _bulk
{ "update" : {"_id" : "1", "_index" : "index1", "retry_on_conflict" : 3} }
{ "doc" : {"field" : "value"} }
{ "update" : { "_id" : "0", "_index" : "index1", "retry_on_conflict" : 3} }
{ "script" : { "source": "ctx._source.counter += params.param1", "lang" : "painless", "params" : {"param1" : 1}}, "upsert" : {"counter" : 1}}
{ "update" : {"_id" : "2", "_index" : "index1", "retry_on_conflict" : 3} }
{ "doc" : {"field" : "value"}, "doc_as_upsert" : true }
{ "update" : {"_id" : "3", "_index" : "index1", "_source" : true} }
{ "doc" : {"field" : "value"} }
{ "update" : {"_id" : "4", "_index" : "index1"} }
{ "doc" : {"field" : "value"}, "_source": true}
8、Term
向量
Term
向量 (Term
Vectors
) 用来存储文档字段的Term
信息(字段文本分词得到的词条)和统计信息。文档可以存储在索引中,也可 以由用户人工提供。Term
向量在默认情况下是实时的。这可以通过将realtime
参数设置为false
来更改。
8.1、返回值
可以请求三种类型的值 :
Term
信息、Term
统计信息和字段统计信息。默认情况下,返回所有字段的所有Term
信息和字段统计信息, 但不返回Term
统计信息。
8.1.1、Term
信息
⬤ Term
的频率 ( 在对应字段中 ) ,这部分信息是始终返回的。
⬤ Term
的位置,需要设置 positions
: true
。
⬤ Term
开始和结束的偏移量,需要设置 offsets
: true
。
⬤ Term
Payloads
(有效载荷,请参考Lucene
相关文档), 需要设置payloads
: true
。
注意:如果请求的信息没有存储在索引中,如果可能它将被即时计算。另外,对于甚至不存在于索引中但由用户提供的文档,也可以计算词条向量。
警告:开始与结束的偏移量假设 UTF
- 16
编码被使用。如果要使用这些偏移量来从原始文本中获取词条,则应确保使用UTF
- 16
对正在使用的子字符串进行编码。
Term
信息在 Elasticsearch
中的具体存储格式如图
8.1.2、字段统计信息
字段统计信息默认是返回的,可以将
field_statistics
设为false
来 禁止返回。字段统计信息包括如下三方面的内容:
⬤ 文档计数,即多少个文档存在这个字段值。
⬤ 文档频率总和,即此字段中所有 Term
的文档频率总和。
⬤ Term
频率总和,即该字段中每个 Term
的总项频率之和
8.1.3、Term
过滤
使用参数
filter
,还可以根据tf
-idf
分数过滤返回的Term
。这有助 于找出文档的特征向量。此功能的工作方式更类似于此查询的第二阶 段。
样例:在下面的示例中,从具有给定 plot
字段值的文档中获得三个用户 “最感兴趣”的关键字。请注意,关键字 Tony
或任何停止词都不是响 应的一部分,因为它们的 tf
- idf
太低。
入参:
GET /imdb/_termvectors
{
"doc": {
"plot": "When wealthy industrialist Tony Stark is forced to build an armored suit after a life-threatening incident, he ultimately decides to use its technology to fight against evil."
},
"term_statistics" : true,
"field_statistics" : true,
"positions": false,
"offsets": false,
"filter" : {
"max_num_terms" : 3,
"min_term_freq" : 1,
"min_doc_freq" : 1
}
}
出参:
{
"_index": "imdb",
"_type": "movies",
"_version": 0,
"found": true,
"term_vectors": {
"plot": {
"field_statistics": {
"sum_doc_freq": 3384269,
"doc_count": 176214,
"sum_ttf": 3753460
},
"terms": {
"armored": {
"doc_freq": 27,
"ttf": 27,
"term_freq": 1,
"score": 9.74725
},
"industrialist": {
"doc_freq": 88,
"ttf": 88,
"term_freq": 1,
"score": 8.590818
},
"stark": {
"doc_freq": 44,
"ttf": 47,
"term_freq": 1,
"score": 9.272792
}
}
}
}
}
8.1.3.1、子参数
key | 说明 |
---|---|
max_num_terms |
每个字段返回的最大Term 数。默认值 为25。也就是只有一个字段最多 25 个Term |
min_term_freq |
忽略源文档中低于此频率的单词。默认值 为1。 |
max_term_freq |
忽略源文档中超过此频率的单词。默认为 无限大 |
min_doc_freq |
忽略文档频率低于这个值的 Term 。默认值 为1。 |
max_doc_freq |
忽略文档频率高于这个值的Term 。默认值 为1。 |
min_word_length |
忽略低于此值的Term 。默认值为0。 |
max_word_length |
忽略高于此值的Term 。默认值为无穷 大。 |
8.2、行为分析
Term
和Field
统计信息是不准确的,仅检索请求文档所在的分片 的信息,而删除的文档不考虑在内。因此,
Term
和Field
统计信息仅 用作相对测量,而绝对数值在此上下文中没有意义。默认情况下,当 请求人工文档的Term
向量时,将随机选择一个分片来获取统计信息。 使用routing
只命中特定的分片。
8.2.1、返回存储词条向量
8.2.1.1、创建一个存储词条向量、有效载荷等的索引
入参:
PUT /twitter
{ "mappings": {
"properties": {
"text": {
"type": "text",
"term_vector": "with_positions_offsets_payloads",
"store" : true,
"analyzer" : "fulltext_analyzer"
},
"fullname": {
"type": "text",
"term_vector": "with_positions_offsets_payloads",
"analyzer" : "fulltext_analyzer"
}
}
},
"settings" : {
"index" : {
"number_of_shards" : 1,
"number_of_replicas" : 0
},
"analysis": {
"analyzer": {
"fulltext_analyzer": {
"type": "custom",
"tokenizer": "whitespace",
"filter": [
"lowercase",
"type_as_payload"
]
}
}
}
}
}
出参:
{
"acknowledged" : true,
"shards_acknowledged" : true,
"index" : "twitter"
}
8.2.1.2、添加一些文档:
入参:
PUT /twitter/_doc/1
{
"fullname" : "John Doe",
"text" : "twitter test test test "
}
PUT /twitter/_doc/2
{
"fullname" : "Jane Doe",
"text" : "Another twitter test ..."
}
出参:
# PUT /twitter/_doc/1
{
"_index" : "twitter",
"_id" : "1",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 1,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 0,
"_primary_term" : 1
}
# PUT /twitter/_doc/2
{
"_index" : "twitter",
"_id" : "2",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 1,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 1,
"_primary_term" : 1
}
8.2.1.3、返回Id
=1 中字段text
的所有信息和统计信息:
入参:
GET /twitter/_termvectors/1
{
"fields" : ["text"],
"offsets" : true,
"payloads" : true,
"positions" : true,
"term_statistics" : true,
"field_statistics" : true
}
出参:
{
"_index" : "twitter",
"_id" : "1",
"_version" : 2,
"found" : true,
"took" : 3,
"term_vectors" : {
"text" : {
"field_statistics" : {
"sum_doc_freq" : 6,
"doc_count" : 2,
"sum_ttf" : 8
},
"terms" : {
"test" : {
"doc_freq" : 2,
"ttf" : 4,
"term_freq" : 3,
"tokens" : [
{
"position" : 1,
"start_offset" : 8,
"end_offset" : 12,
"payload" : "d29yZA=="
},
{
"position" : 2,
"start_offset" : 13,
"end_offset" : 17,
"payload" : "d29yZA=="
},
{
"position" : 3,
"start_offset" : 18,
"end_offset" : 22,
"payload" : "d29yZA=="
}
]
},
"twitter" : {
"doc_freq" : 2,
"ttf" : 2,
"term_freq" : 1,
"tokens" : [
{
"position" : 0,
"start_offset" : 0,
"end_offset" : 7,
"payload" : "d29yZA=="
}
]
}
}
}
}
}
8.2.1.4、自动生成词条向量
未明确存储在索引中的词条向量将自动计算。以下请求返回文档
1
中字段的所有信息和统计信息,即使词条尚未明确存储在索引中。请注意,对于字段text
,术语不会重新生成。
入参:
GET /twitter/_termvectors/1
{
"fields" : ["text", "some_field_without_term_vectors"],
"offsets" : true,
"positions" : true,
"term_statistics" : true,
"field_statistics" : true
}
出参:
{
"_index" : "twitter",
"_id" : "1",
"_version" : 2,
"found" : true,
"took" : 2,
"term_vectors" : {
"text" : {
"field_statistics" : {
"sum_doc_freq" : 6,
"doc_count" : 2,
"sum_ttf" : 8
},
"terms" : {
"test" : {
"doc_freq" : 2,
"ttf" : 4,
"term_freq" : 3,
"tokens" : [
{
"position" : 1,
"start_offset" : 8,
"end_offset" : 12,
"payload" : "d29yZA=="
},
{
"position" : 2,
"start_offset" : 13,
"end_offset" : 17,
"payload" : "d29yZA=="
},
{
"position" : 3,
"start_offset" : 18,
"end_offset" : 22,
"payload" : "d29yZA=="
}
]
},
"twitter" : {
"doc_freq" : 2,
"ttf" : 2,
"term_freq" : 1,
"tokens" : [
{
"position" : 0,
"start_offset" : 0,
"end_offset" : 7,
"payload" : "d29yZA=="
}
]
}
}
}
}
}
8.2.1.5、人造文档
还可以为人造文档生成词条向量,也就是生成索引中不存在的文档。
入参:
GET /twitter/_termvectors
{
"doc" : {
"fullname" : "John Doe",
"text" : "twitter test test test"
}
}
出参:
{
"_index" : "twitter",
"_version" : 0,
"found" : true,
"took" : 111,
"term_vectors" : {
"fullname" : {
"field_statistics" : {
"sum_doc_freq" : 4,
"doc_count" : 2,
"sum_ttf" : 4
},
"terms" : {
"doe" : {
"term_freq" : 1,
"tokens" : [
{
"position" : 1,
"start_offset" : 5,
"end_offset" : 8
}
]
},
"john" : {
"term_freq" : 1,
"tokens" : [
{
"position" : 0,
"start_offset" : 0,
"end_offset" : 4
}
]
}
}
},
"text" : {
"field_statistics" : {
"sum_doc_freq" : 6,
"doc_count" : 2,
"sum_ttf" : 8
},
"terms" : {
"test" : {
"term_freq" : 3,
"tokens" : [
{
"position" : 1,
"start_offset" : 8,
"end_offset" : 12
},
{
"position" : 2,
"start_offset" : 13,
"end_offset" : 17
},
{
"position" : 3,
"start_offset" : 18,
"end_offset" : 22
}
]
},
"twitter" : {
"term_freq" : 1,
"tokens" : [
{
"position" : 0,
"start_offset" : 0,
"end_offset" : 7
}
]
}
}
}
}
}
8.2.1.6、字段分析器
此外,可以使用
per_field_analyzer
参数为不同的字段提供不同 的分析器,这对于以任何方式生成Term
向量都很有用,特别是在使用 人工文档时。当为已经存储Term
向量的字段提供分析器时,将重新生成Term
向量。
入参:
GET /twitter/_termvectors
{
"doc" : {
"fullname" : "John Doe",
"text" : "twitter test test test"
},
"fields": ["fullname"],
"per_field_analyzer" : {
"fullname": "keyword"
}
}
出参:
{
"_index" : "twitter",
"_version" : 0,
"found" : true,
"took" : 2,
"term_vectors" : {
"fullname" : {
"field_statistics" : {
"sum_doc_freq" : 4,
"doc_count" : 2,
"sum_ttf" : 4
},
"terms" : {
"John Doe" : {
"term_freq" : 1,
"tokens" : [
{
"position" : 0,
"start_offset" : 0,
"end_offset" : 8
}
]
}
}
}
}
}
9、refresh
参数
索引、更新、删除和批量
API
支持用refresh
参数来控制请求所做 的更改何时对搜索可见。允许的值如下。
9.1、参数配置
9.1.1、空或 true
操作发生后立即刷新相关的主分片和副本分片 (不是整个索引),以便更新的文档立即显示在搜索结果中。这个设置需要仔细考虑和验证,因为会导致性能下降(从索引和搜索的角度来看)
PUT /test/_doc/1?refresh
{"test":"test"}
PUT /test/_doc/2?refresh=true
{"test":"test"}
9.1.2、wait_for
在返回结果之前,将等待刷新使请求所做的更改可见,这不会强制立即刷新,而是等待刷新发生。
⬤
Elasticsearch
自动刷新,刷新频率是index.refresh_interval
,默认是1s
。这个设置是动态的。调用refresh
API
,或在响应的API
上设置refresh
为true
都将导致刷新,请求将返回。
PUT /test/_doc/3
{"test":"test"}
PUT /test/_doc/4?refresh=false
{"test":"test"}
9.1.3、false
(默认值)
不执行与刷新相关的操作。此请求所做的更改将在请求返回后的某个时间点可见
PUT /test/_doc/4?refresh=wait_for
{"test":"test"}
9.2、如何选择refresh
的值
除非有充分的理由等待更改变为可见,否则始终使用
refresh
=false
如果必须使请求所做的更改与请求同步可见 当
⬤ 设置
refresh
为 ` true时,
Elasticsearch` 将增加更多负载⬤ 设置为
wait_for
;将等待更 长时间,这需要结合实际情况决定。
9.3、强制刷新
如果当已经有
index.max_refresh_listeners
值定义数量 ( 默认 为1000
个) 的请求在该分片上等待刷新时,该请求的行为将如同refresh
设置为true
一样:它将强制刷新。这保证了当该请求返回时, 其更改对搜索可见,同时防止对被阻塞的请求使用未经检查的资源。 如果请求由于监听器槽用完而强制刷新,则其 响应将包含”forced_refresh
”:true
信息。
10、乐观并发控制
Elasticsearch
是分布式的,创建、更新或删除文档时,必须将文档的新版本复制到集群中的其他节点。Elasticsearch
也是异步和并发的,这意味着这些复制请求是并行发送的,并且可能不按顺序到达目的地。Elasticsearch
需要一种方法来确保旧版本的文档永远不会覆盖新版本的文档。保证并发:为了确保旧版本的文档不会覆盖新版本文档,对文档执行的每个操作都由主分片分配一个序列号,序列号随着每个操作的增加而增加,因此新操作的序列号肯定比旧操作的序列号更高。然后,
Elasticsearch
可以使用这个序列号来确保新的文档版本不会被分配了较小序列号的更改覆盖。
举例:以下索引命令将创建一个文档并为其分配初始序列号 _seq_no
和 _primary_term
( _primary_term
和 _seq_no
都 是 整 数),每当主分片发生重新分配时,比如重启、Primary
选举等, _primary_term
会递增1:
入参:
GET twitter/_doc/1
出参:
{
"_index" : "twitter",
"_id" : "1",
"_version" : 14,
"_seq_no" : 15,
"_primary_term" : 1,
"found" : true,
"_source" : {
"fullname" : "John Doe",
"text" : "twitter test test test "
}
}
10.1、乐观更新
_seq_no
和_primary_term
唯一地标识一个变更。通过记下返回 的这两个值,可以确保仅在检索文档后没有对其进行其他更改的情况 下更改文档。这是通过设置索引API
或删除API
的if_seq_no
和if_primary_term
参数来完成的
例如,以下调用将确保向文档中添加标记 tag
,而不会丢失对描述 的任何潜在更改或由其他API添加其他标记:
入参:
PUT /products/_doc/1567?if_seq_no=362&if_primary_term=2
{
"product" : "r2d2",
"details" : "A resourceful astromech droid",
"tags": ["droid"]
}
'
r