Elasticsearch教程 — Document APIs
Elasticsearch文档的操作可以理解成MySQL中的增删改查
操作。
单个文档操作
# 索引中添加数据,如果目标索引的文档已存在,则更新文档并增加版本。当不指定id时为创建文档。
PUT /<target>/_doc/<_id>
POST /<target>/_doc/
PUT /<target>/_create/<_id>
POST /<target>/_create/<_id>
# 使用示例
POST my-index-000001/_doc/
{
"@timestamp": "2099-11-15T13:12:00",
"message": "GET /search HTTP/1.1 200 1070000",
"user": {
"id": "kimchy"
}
}
# 查询文档
GET <index>/_doc/<_id> # 获取文档详情
HEAD <index>/_doc/<_id> # 使用 HEAD 验证文档是否存在
GET <index>/_source/<_id> # 获取文档
HEAD <index>/_source/<_id> # 验证文档是否存在
# 删除文档
DELETE /<index>/_doc/<_id>
# 更新文档
POST /<index>/_update/<_id>
POST test/_update/1
{
"doc": {
"name": "new_name"
}
}
POST test/_update/1
{
"script" : {
"source": "ctx._source.counter += params.count",
"lang": "painless",
"params" : {
"count" : 4
}
}
}
批量操作
# 从一个或多个索引中检索多个文档。如果在请求 URI 中指定索引,则只需在请求正文中指定文档 ID。
GET /_mget
GET /<index>/_mget
GET /_mget
{
"docs": [
{
"_index": "testindex", # 如果在查询参数中没指定索引,这里就需指定索引
"_id": "1", # 必须,文档id
"_source": [ "field3", "field4" ] # 返回字段
},
{
"_index": "testindex",
"_id": "2",
"_source": {
"include": [ "user" ], # 返回的字段
"exclude": [ "user.location" ] # 过滤字段
}
}
]
}
GET /my-index-000001/_mget
{
"ids" : ["1", "2"]
}
# 在单个 API 调用中执行多个索引或删除操作。这减少了开销并且可以大大提高索引速度。
POST /_bulk
POST /<target>/_bulk
# 请求主体中包含的新行分隔的列表create,delete,index,和update行动及其相关的源数据。
# create(可选,字符串)创建文档,如果它不存在。下一行必须包含要建立索引的源数据。不过不存在_id那么自动生成id
# delete(可选,字符串)从索引中删除指定的文档。_id必须
# index(可选,字符串)替换指定文档。_id如果存在,则替换文档并增加版本。以下行必须包含要建立索引的源数据。_id如果不存在自动生成新文档
# update(可选,字符串)执行部分文档更新。以下行必须包含部分文档和更新选项。_id必须
# doc(可选,对象)要索引的部分文档。update操作的下一行所需。
# 批量API的响应包含请求中每个操作的单独结果,按提交的顺序返回。单个操作的成功或失败不会影响请求中的其他操作。
# 示例,注意其语法格式。
POST _bulk
{ "index" : { "_index" : "test", "_id" : "1" } }
{ "field1" : "value1" }
{ "delete" : { "_index" : "test", "_id" : "2" } }
{ "create" : { "_index" : "test", "_id" : "3" } }
{ "field1" : "value3" }
{ "update" : {"_id" : "1", "_index" : "test"} }
{ "doc" : {"field2" : "value2"} }
# retry_on_conflict 指定一个更新应重试多少次
# 在update操作时,支持的选项包括 doc script lang params upsert doc_as_upsert _source
POST _bulk
{ "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 }
# 注意
# index/create
# 删除查询到的文档
POST /<target>/_delete_by_query
# 更新查询到的文档
POST /<target>/_update_by_query
index/create
第一步判断是确定插入的文档是否指定id,如果没有指定id,系统会默认生成一个唯一id。
这种情况下,不管index还是create会直接add文档。如果用户指定了id,那么就会走update,update成本比add要高。
第二步判断,会检查版本号是否冲突,只有正确的版本号才会执行插入,否则会插入失败。
通过源码分析可以了解到,获取版本号的这个过程,是通过id来get文档,但无论是index还是create都不会get整个doc的全部内容,只是get出了版号。这也从一定程度上减少了系统开销。
总结:
- 自动生成的 id,则 index/create 都采用 add 方式
- 业务指定的 id,则 index/create 都采用 update 方式
- 检查版本号是否冲突
update
由于 Lucene 中的 update 其实就是覆盖替换,并不支持针对特定 Field 进行修改,Elasticsearch 中的 update 为了实现针对特定字段修改,在 Lucene 的基础上做了一些改动。
每次 update 都会调用 InternalEngine 中的 get 方法,来获取整个文档信息,从而实现针对特定字段进行修改,这也就导致了每次更新要获取一遍原始文档,性能上会有很大影响。
所以根据使用场景,有时候使用 index 会比 update 好很多。
index和create区别
index 和 create 都会检查 _version 版本号。
index 插入时分两种情况:
- 没有指定 _version,那对于已有的doc,_version会递增,并对文档覆盖。
- 指定_version,如果与已有的文档 _version 不相等,则插入失败;如果相等则覆盖,_version递增。
create 插入时对于已有的文档,不会创建新文档,即插入失败,会抛出一个已经存在的异常。
用途解释:
在批量请求的时候最好使用 create 方式进行导入。假如你批量导入一个大小为500MB 的文件,中途突然网络中断,可能其中有5万条数据已经导入,那么第二次尝试导入的时候,如果选用 index 方式,那么前5万条数据又会重复导入,增加了很多额外的开销,如果是 create 的话,elasticsearch 针对 bulk 操作机制是忽略已经存在的(当然在 bulk 完成后会返回哪些数据是重复的),这样就不会重复被导入了
最后更新于 2021-12-28 16:35:56 并被添加「Elasticsearch教程」标签,已有 961 位童鞋阅读过。
本站使用「署名 4.0 国际」创作共享协议,可自由转载、引用,但需署名作者且注明文章出处
此处评论已关闭