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 是一个固定的上下文变量,它代表当前正在处理的文档的源数据。这个变量在脚本执行过程中是固定的,不会改变其含义,但它的内容会根据你正在处理的具体文档而变化。

解释

  1. 固定变量:
    • ctx._source 是一个预定义的变量,它在脚本中始终表示当前文档的源数据。
    • 这个变量是只读的,你不能直接修改 ctx._source,但可以通过它来访问和修改文档中的字段。
  2. 内容变化:
    • 尽管 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"]
    }
     

注意事项

  1. 只读性:
    • ctx._source 本身是只读的,你不能直接修改 ctx._source,但可以通过它来修改文档中的字段。
  2. 字段修改:
    • 你可以通过 ctx._source.fieldName 来访问和修改字段值。例如:
      java
      复制
      ctx._source.counter += params.count
       
  3. 文档结构:
    • 如果文档中没有某个字段,直接访问该字段会导致 null 值。为了避免错误,可以在脚本中进行检查。例如:
      java
      复制
      if (ctx._source.containsKey('counter')) {
        ctx._source.counter += params.count
      }
       

总结

ctx._source 是一个固定的上下文变量,始终表示当前文档的源数据。它的内容会根据你正在处理的具体文档而变化,但其含义是固定的。通过 ctx._source,你可以访问和修改文档中的字段值。


posted @ 2025-08-29 11:16  人在代码在  阅读(10)  评论(0)    收藏  举报