【Elasticsearch教程2】 更新文档 painless script案例
2023-09-27 14:26:50 时间
版本约定
本系列博客ES版本如下:
- Elasticsearch
7.17.X
- Spring Data Elasticsearch
4.4.X
Elasticsearch下载地址
Spring Data Elasticsearch 下载地址
更新文档API
- 对于简单点的更新,可以在doc里写新的文档内容来更新文档
- 对于复杂点的更新,可以使用painless script脚本更新文档
初始化数据
PUT pigg_test/_doc/1
{
"name": "亚瑟王",
"age": 33
}
1 doc更新
把需要更新的字段放到doc里面,已有的字段会更新,新的字段会添加进文档。
POST pigg_test/_update/1
{
"doc": {
"age": 32,
"word": "向我祈求怜悯吧"
}
}
再次查询id=1的文档发现age的值改变了,并且添加了新的字段word。
{
"_source" : {
"name" : "亚瑟王",
"age" : 32,
"word" : "向我祈求怜悯吧"
}
}
当文档不存在时,更新会报错,可以设置"doc_as_upsert": true
就会创建文档:
当id=2的文档不存在时,会创建该文档
POST pigg_test/_update/2
{
"doc": {
"name": "死亡骑士",
"age": 32,
"word": "向我祈求怜悯吧"
},
"doc_as_upsert": true
}
2 painless script更新
painless
是Elasticsearch的默认脚本语言,它具有像 Groovy 那样的语法。
painless
可以用在更新文档,也可以用来写查询文档的查询条件。
下面就先写些更新文档的例子,用painless
脚本查询文档在后期博客再做详细介绍。
修改字段的值
POST pigg_test/_update/1
{
"script": {
"source": "ctx._source.word = '我会狠狠地拒绝你'"
}
}
上面的脚步也可以简写为如下格式:
POST pigg_test/_update/1
{
"script": "ctx._source.word = '我会狠狠地拒绝你'"
}
对数值类型进行数学计算
POST pigg_test/_update/1
{
"script": "ctx._source.age += 1"
}
给文档添加一个新的字段act
POST pigg_test/_update/1
{
"script": "ctx._source.act = ['誓约之盾']"
}
给act数组再添加一项值
POST pigg_test/_update/1
{
"script": "ctx._source.act.add('回旋打击')"
}
当act数组中不存在“圣剑裁决”时,才添加“圣剑裁决”
POST pigg_test/_update/1
{
"script": {
"source": "if(!ctx._source.act.contains(params.act)) {ctx._source.act.add(params.act)}",
"lang": "painless",
"params": {
"act": "圣剑裁决"
}
}
}
当act数组中存在“圣剑裁决”时,才删除“圣剑裁决”
POST pigg_test/_update/1
{
"script":{
"source": "if(ctx._source.act.contains(params.act)) {ctx._source.act.remove(ctx._source.act.indexOf(params.act))}",
"lang": "painless",
"params": {
"act": "圣剑裁决"
}
}
}
添加一个新的字段newName
,它的值和name
相等
POST pigg_test/_update/1
{
"script": "ctx._source.newName = ctx._source.name"
}
删除字段newName
,但是不修改mapping
POST pigg_test/_update/1
{
"script": "ctx._source.remove('newName')"
}
3 Update By Query
当需要对查询条件匹配到的文档更新时,可以使用_update_by_query,在script
同级加上query
查询语句。
POST pigg_test/_update_by_query?conflicts=proceed
{
"script": {
"source": "ctx._source.age+=1",
"lang": "painless"
},
"query": {
"term": {
"name.keyword": {
"value": "亚瑟王"
}
}
}
}
Java API中使用painless script
1 Elasticsearch Java API
写一个方法,根据查询条件执行script更新文档:
- 第一个参数是索引名称
- 第二个参数是查询条件
- 第三个参数是要更新的script脚步
public static BulkByScrollResponse updateByQuery(String index, QueryBuilder query, String strScript) {
BulkByScrollResponse bulkResponse = null;
try {
UpdateByQueryRequest request = new UpdateByQueryRequest(index);
request.setConflicts("proceed");
request.setQuery(query);
Script script = new Script(
ScriptType.INLINE, "painless",
strScript,
Collections.emptyMap());
request.setScript(script);
bulkResponse =
restHighLevelClient.updateByQuery(request, RequestOptions.DEFAULT);
} catch (IOException e) {
log.error("ES更新异常", e.getMessage());
}
return bulkResponse;
}
调用上面方法的案例:将state更新为1
IdsQueryBuilder idsQueryBuilder = QueryBuilders.idsQuery().addIds(ids.stream().toArray(String[]::new));
RestfulElasticsearchUtils.updateByQuery(
"pigg_test",
idsQueryBuilder,
"ctx._source['state']='1'"
);
2 Spring Data Elasticsearch
这里用Spring Data Elasticsearch的UpdateQuery
举例:
根据查询条件,将文档的state
的值更新为INVALID
public long forceInvalidByQuery(QueryBuilder queryBuilder) {
NativeSearchQuery query = new NativeSearchQueryBuilder()
.withQuery(queryBuilder)
.build();
UpdateQuery updateQuery = UpdateQuery.builder(query)
.withScriptType(ScriptType.INLINE)
.withScript("ctx._source['state'] = params['newState']").withLang("painless")
.withParams(Collections.singletonMap("newState", StateEnum.INVALID.getValue()))
.withAbortOnVersionConflict(false)
.build();
ByQueryResponse byQueryResponse = operations.updateByQuery(updateQuery, getIndexCoordinates());
return byQueryResponse.getUpdated();
}
相关文章
- MEMS激光雷达监测法兰克福机场客流量应用案例
- Socket编程:之TCP案例
- java中值传递和引用传递案例剖析
- Forrester最佳案例:西班牙银行的创新计划
- C语言:快速排序算法案例
- 大数据失败案例之七宗罪
- 【问题记录】Process finished with exit code -1073740791 (0xC0000409) 注:LSTM股票预测案例中
- [供应链·案例篇]疫情影响下的全球十大零售商都做了些什么
- 【供应链案例】仁和药业:拨开供应链现状迷雾,实现业务效率高增长
- [Spring Framework]AOP经典案例、AOP总结
- 前端笔记(9) Vue3 async await 循环调接口使用案例
- 第15.37节 PyQt(Python+Qt)入门学习:containers容器类部件QMdiArea多文档界面部件详解及编程开发案例
- 第8.5节 Python类中的__new__方法和构造方法__init__关系深入剖析:执行顺序及参数关系案例详解
- 第7.18节 案例详解:Python类中装饰器@staticmethod定义的静态方法
- 大型网站技术架构——核心原理与案例分析(三)
- Elasticsearch查询文档--常见API篇(附详细代码和案例图文)