es script 脚本
BigDecimal bd = new BigDecimal(salaryCalculationTaxEsSave.getMonthTax());
bd = bd.setScale(2, RoundingMode.HALF_UP);
List<UpdateQuery> updateRequestList = new ArrayList<>();
// 使用 HashMap 创建参数
Map<String, Object> params = new HashMap<>(BaseConstant.ONE_VALUE);
params.put("newHeadValue", bd.toString());
// 构建内联脚本字符串
String scriptString =
"if (ctx._source.salaryHead != null && ctx._source.salaryHead.headValueList != null) { " +
" for (def item : ctx._source.salaryHead.headValueList) { " +
" if (item.headName == '个税') { " +
" item.headValue = params.newHeadValue;" +
" break;" +
" }" +
" }" +
"}";
// 构建 UpdateQuery
UpdateQuery updateQuery = UpdateQuery.builder(String.valueOf(salaryCalculationTaxEsSave.getEmpId()))
.withScript(scriptString)
.withParams(params)
.build();
// 添加到更新请求列表
updateRequestList.add(updateQuery);
try {
// 执行批量更新
log.info("批量更新实发工资参数:{}", JSONUtil.toJsonStr(updateRequestList));
if(!CollectionUtils.isEmpty(updateRequestList)){
BulkOptions bulkOptions = BulkOptions.builder().withRefreshPolicy(RefreshPolicy.IMMEDIATE).build();
elasticsearchTemplate.bulkUpdate(updateRequestList,bulkOptions,IndexCoordinates.of(salaryCalculationTaxEsSave.getPayrollId()));
}
} catch (Exception e) {
// 处理异常
e.printStackTrace();
throw new ServiceException("批量更新失败");
}
es信息:
{
"_index" : "1960633038094245889",
"_type" : "_doc",
"_id" : "1960620137651204096",
"_score" : 1.0,
"_source" : {
"id" : 1960620137651204096,
"salaryHead" : {
"headValueList" : [
{
"headName" : "应发工资",
"headType" : 2,
"formItemNo" : "FI202412101050516137",
"headValue" : "9290.32000",
"status" : 1
},
解析脚本:PUT my-index-000001/_doc/1
{ "counter" : 1, "tags" : ["red"] }
POST my-index-000001/_update/1
{ "script" :
{ "source": "ctx._source.counter += params.count", "lang": "painless",
"params" : { "count" : 4 }
}
}
这段代码展示了如何在 Elasticsearch 中使用 Painless 脚本语言来更新文档。下面逐步解析这段代码:
1. 创建文档
JSON
PUT my-index-000001/_doc/1
{
"counter" : 1,
"tags" : ["red"]
}
-
PUT my-index-000001/_doc/1:向 Elasticsearch 的my-index-000001索引中创建一个文档,文档的 ID 是1。 -
文档内容:
-
counter字段的值是1。 -
tags字段是一个数组,包含一个字符串"red"。
-
2. 更新文档
JSON
POST my-index-000001/_update/1
{
"script" : {
"source": "ctx._source.counter += params.count",
"lang": "painless",
"params" : {
"count" : 4
}
}
}
-
POST my-index-000001/_update/1:向 Elasticsearch 的my-index-000001索引中更新 ID 为1的文档。 -
script:定义了一个脚本,用于更新文档。-
source:脚本的内容,使用 Painless 脚本语言编写。-
ctx._source.counter += params.count:将文档中的counter字段的值加上params.count的值。
-
-
lang:指定脚本语言为painless。 -
params:定义了脚本的参数。-
count:参数的值为4。
-
-
3. 脚本执行过程
-
当执行更新操作时,Elasticsearch 会解析脚本
ctx._source.counter += params.count。 -
ctx._source表示文档的当前内容。 -
ctx._source.counter表示文档中counter字段的值。 -
params.count表示脚本参数中的count值,即4。 -
脚本执行后,
counter字段的值会从1更新为1 + 4 = 5。
4. 更新后的文档
更新操作完成后,文档的内容将变为:
JSON
{
"counter" : 5,
"tags" : ["red"]
}
总结
这段代码展示了如何使用 Elasticsearch 的 Painless 脚本语言来更新文档中的字段值。通过脚本,可以动态地修改文档的内容,而无需先获取文档再进行更新操作。
ctx._source 是固定变量吗?会变吗?
在 Elasticsearch 的 Painless 脚本中,
ctx._source 是一个固定的上下文变量,它代表当前正在处理的文档的源数据。这个变量在脚本执行过程中是固定的,不会改变其含义,但它的内容会根据你正在处理的具体文档而变化。解释
-
固定变量:
-
ctx._source是一个预定义的变量,它在脚本中始终表示当前文档的源数据。 -
这个变量是只读的,你不能直接修改
ctx._source,但可以通过它来访问和修改文档中的字段。
-
-
内容变化:
-
尽管
ctx._source的含义是固定的,但它的内容会根据你正在处理的文档而变化。 -
每次执行脚本时,
ctx._source会指向当前正在处理的文档的源数据。
-
示例
假设你有一个文档,其内容如下:
JSON
{
"counter": 1,
"tags": ["red"]
}
当你执行以下脚本时:
JSON
POST my-index-000001/_update/1
{
"script" : {
"source": "ctx._source.counter += params.count",
"lang": "painless",
"params" : {
"count" : 4
}
}
}
-
ctx._source的内容是:JSON{ "counter": 1, "tags": ["red"] } -
脚本执行后,
ctx._source.counter的值从1变为5,文档的内容变为:JSON{ "counter": 5, "tags": ["red"] }
注意事项
-
只读性:
-
ctx._source本身是只读的,你不能直接修改ctx._source,但可以通过它来修改文档中的字段。
-
-
字段修改:
-
你可以通过
ctx._source.fieldName来访问和修改字段值。例如:javactx._source.counter += params.count
-
-
文档结构:
-
如果文档中没有某个字段,直接访问该字段会导致
null值。为了避免错误,可以在脚本中进行检查。例如:javaif (ctx._source.containsKey('counter')) { ctx._source.counter += params.count }
-
总结
ctx._source 是一个固定的上下文变量,始终表示当前文档的源数据。它的内容会根据你正在处理的具体文档而变化,但其含义是固定的。通过 ctx._source,你可以访问和修改文档中的字段值。

浙公网安备 33010602011771号