第五阶段 44 · Painless 脚本与 runtime fields(运行时字段)
44 · Painless 脚本与 runtime fields运行时字段阶段第五阶段 / 进阶ESscript fields / script query / update script / runtime fields | PostgreSQL表达式列 / 生成列 /UPDATE SET col expr1. 概念Painless是 ES 内置脚本语言类 Java。四个高频用途用途作用SQL 类比script field查询时算一个临时字段返回SELECT price*qty AS amountscript query用脚本做过滤条件WHERE price*qty 1000update script按脚本原地改文档UPDATE SET n n 1runtime fieldmapping 里定义查询时计算的字段不占存储生成列虚拟原则脚本灵活但慢能用普通字段/查询解决就别上脚本。2. PostgreSQL 对照-- 表达式列SELECTprice*qtyASamountFROMsales;-- 生成列存储或虚拟≈ runtime fieldALTERTABLEsalesADDCOLUMNamountnumericGENERATED ALWAYSAS(price*qty)STORED;-- 脚本更新UPDATEsalesSETview_countview_count1WHEREid1;3. ES DSL3.1 script field查询时算字段GET sales_idx/_search { script_fields: { amount: { script: { source: doc[price].value * doc[qty].value } } } }3.2 script query脚本过滤GET sales_idx/_search { query: { bool: { filter: { script: { script: doc[price].value * doc[qty].value params.min, params: { min: 1000 } } } } } }3.3 update by script自增POST sales_idx/_update/1 { script: { source: ctx._source.view_count params.n, params: { n: 1 } } }3.4 runtime field查询时计算的虚拟字段推荐PUT sales_idx/_mapping { runtime: { amount: { type: double, script: { source: emit(doc[price].value * doc[qty].value) } } } } GET sales_idx/_search { query: { range: { amount: { gte: 1000 } } } } // 像普通字段一样用4. Spring Boot 实现ComponentpublicclassDoc44Script{AutowiredprivateElasticsearchClientelasticsearchClient;/** 用 params 传参的脚本过滤price*qty min */publicListMapString,ObjectbyAmountScript(StringindexName,doublemin)throwsIOException{SearchResponseMaprespelasticsearchClient.search(s-s.index(indexName).query(q-q.bool(b-b.filter(f-f.script(sc-sc.script(scr-scr.source(doc[price].value * doc[qty].value params.min).params(min,JsonData.of(min))))))),Map.class);returnresp.hits().hits().stream().map(Hit::source).filter(Objects::nonNull).collect(Collectors.toList());}}importco.elastic.clients.json.JsonData。动态值一律走params别拼进source字符串——既能被脚本缓存复用又避免注入。5. 坑与最佳实践能不用脚本就不用脚本不走倒排、逐文档执行慢且难缓存。一定用params传参相同source 不同params才会命中脚本编译缓存。doc[field]vsparams._sourcedoc[...]读 doc_values快text不可用ctx._source/params._source读原文慢。过滤/排序用doc[...]。runtime field 换取灵活性查询时算、零存储、可随时改定义代价是每次查询都算重查询慎用。update script 注意并发高并发自增用_update 乐观锁if_seq_no/if_primary_term。