Spring Data Elasticsearch批量更新报parsing_exception错误求助
问题原因
你错误地将update_by_query的完整请求体(包含query和script)传给了StringQuery,但StringQuery的作用仅定义查询条件,而非整个更新请求。当Spring Data Elasticsearch将该内容发送给Elasticsearch时,ES会尝试把整个JSON当作查询语句解析,而根节点的query字段并非合法的查询类型,因此抛出parsing_exception: unknown query [query]异常。
修复方案
以下提供两种可行的修复方式,推荐使用第一种类型安全的API构建方式:
方式一:使用Spring Data Elasticsearch API构建(推荐)
通过API分别构建查询条件和更新脚本,避免手写JSON的语法问题:
@Slf4j @Service @RequiredArgsConstructor public class ElasticsearchBulkUpdateService { private final ElasticsearchOperations elasticsearchOperations; public void updateProfitForPattern(String idPattern, String indexName) { log.info("Executing bulk update on index '{}':", indexName); // 1. 构建wildcard查询条件 Query query = Query.builder() .withQuery(q -> q.wildcard(w -> w.field("id").value("*-14030701"))) .build(); // 2. 构建Painless更新脚本 Script script = Script.of(ScriptType.INLINE, "painless", """ if (ctx._source.fundUnit != null) { ctx._source.profit = ctx._source.fundUnit * 5; } """, Collections.emptyMap()); // 3. 关联查询与脚本,构建UpdateQuery UpdateQuery updateQuery = UpdateQuery.builder(query) .withScript(script) .build(); IndexCoordinates indexCoordinates = IndexCoordinates.of(indexName); ByQueryResponse byQueryResponse = elasticsearchOperations.updateByQuery(updateQuery, indexCoordinates); System.err.println(byQueryResponse); } }
方式二:拆分StringQuery与脚本(兼容手写JSON场景)
如果习惯手写查询JSON,需确保StringQuery仅包含查询条件部分,脚本单独配置:
@Slf4j @Service @RequiredArgsConstructor public class ElasticsearchBulkUpdateService { private final ElasticsearchOperations elasticsearchOperations; public void updateProfitForPattern(String idPattern, String indexName) { log.info("Executing bulk update on index '{}':", indexName); // StringQuery仅传入查询条件的JSON(原Dev Tools请求中query字段的内容) Query query = new StringQuery(""" { "wildcard": { "id": { "value": "*-14030701" } } } """); // 单独构建更新脚本 Script script = Script.of(ScriptType.INLINE, "painless", """ if (ctx._source.fundUnit != null) { ctx._source.profit = ctx._source.fundUnit * 5; } """, Collections.emptyMap()); UpdateQuery updateQuery = UpdateQuery.builder(query) .withScript(script) .build(); IndexCoordinates indexCoordinates = IndexCoordinates.of(indexName); ByQueryResponse byQueryResponse = elasticsearchOperations.updateByQuery(updateQuery, indexCoordinates); System.err.println(byQueryResponse); } }
核心逻辑说明
UpdateQuery需要分别指定查询筛选条件和更新执行脚本,两者是独立配置项,不能合并为一个查询字符串传入。Spring Data Elasticsearch会基于这两个配置,组装成合法的update_by_query请求发送给Elasticsearch。
内容的提问来源于stack exchange,提问作者milad sorour
相关产品推荐
相关产品推荐

