卖渔具的亲戚做网站,图怪兽海报制作官网,电子商务营销优势,湛江网站制作优化二、ElasticSearch 学习 ELK 进阶
#xff08;1#xff09;文档局部更新 我们也说过文档是不可变的——它们不能被更改#xff0c;只能被替换。 update API必须遵循相同的规则。表面看来#xff0c;我们似乎是局部更新了文档的位置#xff0c;内部却是像我们之前说的一样…二、ElasticSearch 学习 ELK 进阶
1文档局部更新 我们也说过文档是不可变的——它们不能被更改只能被替换。 update API必须遵循相同的规则。表面看来我们似乎是局部更新了文档的位置内部却是像我们之前说的一样简单的使用 update API处理相同的检索*-修改-*重建索引流程我们也减少了其他进程可能导致冲突的修改。 最简单的 update 请求表单接受一个局部文档参数 doc 它会合并到现有文档中——对象合并在一起存在的标量字段被覆盖新字段被添加。举个例子我们可以使用以下请求为博客添加一个 tags 字段和一个 views 字段
POST /website/blog/1/_update
{doc : {tags : [ testing ],views: 0}
}返回
{_index : website,_id : 1,_type : blog,_version : 3
}查询当前的文档信息
GET /website/blog/1{_index: website,_type: blog,_id: 1,_version: 3,found: true,_source: {title: My first blog entry,text: Starting to get the hang of this...,tags: [ testing ], views: 0}
}
2使用脚本局部更新
使用Groovy脚本这时候当API不能满足要求时Elasticsearch允许你使用脚本实现自己的逻辑。脚本支持非常多的API例如搜索、排序、聚合和文档更新。脚本可以通过请求的一部分、检索特殊的 .scripts 索引或者从磁盘加载方式执行。
默认的脚本语言是Groovy一个快速且功能丰富的脚本语言语法类似于Javascript。它
在一个沙盒(sandbox)中运行以防止恶意用户毁坏Elasticsearch或攻击服务器。1、硬编码更新
脚本能够使用 update API改变 _source 字段的内容它在脚本内部以 ctx._source 表示。例如我们可以使用脚本增加博客的 views 数量
POST /website/blog/1/_update
{script : ctx._source.views1
}2、软编码更新
我们还可以使用脚本增加一个新标签到 tags 数组中。在这个例子中我们定义了一个新标签 做为参数而不是硬编码在脚本里。这允许Elasticsearch未来可以重复利用脚本而不是在想 要增加新标签时必须每次编译新脚本
#添加新的tag到文档中
POST /website/blog/1/_update
{script: {source: ctx._source.tags.addAll(params.new_tag),params: {new_tag: [search]}}
}查询结果
GET /website/blog/1{_index : website,_type : blog,_id : 1,_version : 10,_seq_no : 11,_primary_term : 1,found : true,_source : {title : My first blog entry,text : Just trying this out...3,views : 2,tags : [testing,search]}
}3、更新可能不存在的文档
比如
我们要在Elasticsearch中存储浏览量计数器。每当有用户访问页面我们增加这个页面的浏览量。但如果这是个新页面我们并不确定这个计数器存在与否。当我们试图更新一个不存在的文档更新将失败。
在这种情况下我们可以使用 upsert 参数定义文档来使其不存在时被创建将自动创建该索引信息。
POST /website_new/pageviews/1/_update
{script: {source: ctx._source.views1},upsert: {views: 1}
}查询自动创建的信息
GET /website_new/pageviews/_search
{}//返回值
{took : 472,timed_out : false,_shards : {total : 1,successful : 1,skipped : 0,failed : 0},hits : {total : {value : 1,relation : eq},max_score : 1.0,hits : [{_index : website_new,_type : pageviews,_id : 1,_score : 1.0,_source : {views : 3}}]}
}4、更新和冲突
为了避免丢失数据 update API在检索**(retrieve)阶段检索文档的当前 _version 然后在重建索引(reindex)阶段通过 index 请求提交。如果其他进程在检索(retrieve)和重建索引(reindex)**阶段修改了文档 _version 将不能被匹配然后更新失败。
对于多用户的局部更新文档被修改了并不要紧。例如两个进程都要增加页面浏览量增加的顺序我们并不关心——如果冲突发生我们唯一要做的仅仅是重新尝试更新既可。
这些可以通过 retry_on_conflict 参数设置重试次数来自动完成这样 update 操作将会在发生错误前进行重试这个值默认为0。
POST /website/pageviews/1/_update?retry_on_conflict5
{script : ctx._source.views1,upsert: {views: 0}
}配置参数retry_on_conflict5代表在错误发生前重试更新5次。这种重试方式更适合于count这种与顺序无关的操作。
5、检索多个文档
使用ElasticSearch检索多个文档可以使用合并多个请求来避免每个请求单独的网络开销。
如果你需要从Elasticsearch中检索多个文档相对于一个一个的检索更快的方式是在一个请求中使用multi-get或者 mget API。
mget
mget API参数是一个 docs 数组数组的每个节点定义一个文档的 _index 、 _type 、 _id 元数据。但是如果你只想检索一个或者几个确定的字段也可以使用 _source参数进行设置
//比如已下操作则是查询两个index的信息整合在一起返回
POST /_mget
{docs: [{_index: website,_type: blog,_id: 2},{_index: website_new,_type: pageviews,_id: 1,_source: views}]
}
//返回结果是
{docs : [{_index : website,_type : blog,_id : 2,_version : 10,_seq_no : 5,_primary_term : 1,found : true,_source : {title : My first external blog entry,text : This is a piece of cake...}},{_index : website_new,_type : pageviews,_id : 1,_version : 3,_seq_no : 2,_primary_term : 1,found : true,_source : {views : 3}}]
}
//也会通过docs组成数组的方式返回如果想检索的在同一个_index中可以直接使用ids的方式进行检索
POST /website/blog/_mget
{ids:[2,1]
}//返回
{docs : [{_index : website,_type : blog,_id : 2,_version : 10,_seq_no : 5,_primary_term : 1,found : true,_source : {title : My first external blog entry,text : This is a piece of cake...}},{_index : website,_type : blog,_id : 1,_version : 11,_seq_no : 12,_primary_term : 1,found : true,_source : {title : My first blog entry,text : Just trying this out...3,views : 3,tags : [testing,search]}}]
}我们还可以使用设置_type的方式进行检索
POST /website_new/bolg/_mget
{docs:[{_id:2},{_type:pageviews,_id:1}]
}//返回
{docs : [{_index : website_new,_type : bolg,_id : 2,found : false},{_index : website_new,_type : pageviews,_id : 1,_version : 3,_seq_no : 2,_primary_term : 1,found : true,_source : {views : 3}}]
}可以发现在website_new index的bolg 类型下没有id为2的数据所以返回值found为false所以再使用_mget的时候需要检查found是否为false。
6、批量操作
就像 mget 允许我们一次性检索多个文档一样 bulk API允许我们使用单一请求来实现多个文档的 create 、 index 、 update 或 delete 。
也就是说我们可以铜bulk API的方式使用一个请求完成create、index、update、delete一系列的操作。这对索引类似于日志活动这样的数据流非常有用它们可以 以成百上千的数据为一个批次按序进行索引。
bulk 请求体如下
{ action: { metadata }}\n
{ request body }\n
{ action: { metadata }}\n
{ request body }\n
...这种格式类似于用 “\n” 符号连接起来的一行一行的JSON文档流**(stream)**。两个重要的点需注意
每行必须以 “\n” 符号结尾包括最后一行。这些都是作为每行有效的分离而做的标记。每一行的数据不能包含未被转义的换行符它们会干扰分析——这意味着JSON不能被美化打印。
将这些放在一起 bulk 请求表单是这样的
POST /_bulk
{ delete: { _index: website, _type: blog, _id: 123 }}
{ create: { _index: website, _type: blog, _id: 123 }}
{ title: My first blog post }
{ index: { _index: website, _type: blog }}
{ title: My second blog post }
{ update: { _index: website, _type: blog, _id: 123, _retry_on_conflict :
{ doc : {title : My updated blog post} }通过bulk api操作Elasticsearch响应包含一个 items 数组它罗列了每一个请求的结果结果的顺序与我们请求的顺序相同
{took: 4,errors: false,items: [{delete: {_index: website,_type: blog,_id: 123,_version: 2,status: 200,found: true}},{create: {_index: website,_type: blog,_id: 123,_version: 3,status: 201}},{create: {_index: website,_type: blog,_id: EiwfApScQiiy7TIKFxRCTw,_version: 1,status: 201}},{update: {_index: website,_type: blog,_id: 123,_version: 4,status: 200}}]
}但是在使用批量请求的时候需要注意一点的是 整个批量请求需要被加载到我们请求节点的内存里面请求越大那么给其他请求使用的内存空间就越小。 有一个最佳的 bulk 请求大小。超过这个大小性能不再提升而且可能降低这个最佳的大小与当前的硬件、网络环境、和搜索的复杂度有关。 通常可以试着使用线性增长的方式进行寻找这个平衡点弱随着大小的增长当性能开始降低说明你每个批次的大小太大了。开始的数量可以在1000 ~ 5000个文档之间如果你的文档非常大可以使用较小的批次通常着眼于你请求批次的物理大小是非常有用的。一千个1kB的文档和一千个1MB的文档大不相同。一个好的批次最好保持在5 ~15MB大小间。