RestHighLevelClient迁移:ElasticSearch Java API Client如何提交批量删除任务?
从RestHighLevelClient迁移到Elasticsearch Java API Client:批量删除后台任务提交问题
问题背景
原RestHighLevelClient已弃用,迁移到Elasticsearch Java API Client后,批量删除数万至数百万文档的后台任务提交功能找不到直接替代。原有代码如下:
// import org.elasticsearch.index.reindex.DeleteByQueryRequest; private String deleteLarge(String indexName, Long categoryNumber, Optional<Long> age) { BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery() .filter(QueryBuilders.matchQuery("category", categoryNumber)); age.ifPresent(a -> boolQueryBuilder .filter(QueryBuilders.matchQuery("age", a))); DeleteByQueryRequest request = new DeleteByQueryRequest(indexName) .setQuery(boolQueryBuilder) .setSlices(10); try { TaskSubmissionResponse taskSubmissionResponse = restHighLevelClient.submitDeleteByQueryTask(request, RequestOptions.DEFAULT); logger.info("DeleteByQueryTask task id: {}", taskSubmissionResponse.getTask()); return taskSubmissionResponse.getTask(); } catch (Exception e) { logger.error(e.getMessage()); } return null; }
核心需求是将删除任务提交到ES后台异步执行,而非等待完成,但新客户端的ElasticsearchTasksClient仅支持查询/取消任务,无提交入口。
问题解答
1. ES是否不再支持任务提交,或将其逐步弃用?
ES并没有弃用后台任务提交功能,底层REST API(如_delete_by_query带wait_for_completion=false参数)依然完全支持。只是新的Java API Client没有像旧客户端那样封装专门的submitXXXTask方法,而是通过请求参数来控制任务是否后台执行。
2. 若仍支持,是否有其他方式提交新任务?
可以通过在DeleteByQueryRequest中设置wait_for_completion=false参数,配合异步客户端调用,实现和原有submitDeleteByQueryTask完全一致的效果。示例代码如下:
import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient; import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery; import co.elastic.clients.elasticsearch._types.query_dsl.QueryBuilders; import co.elastic.clients.elasticsearch.core.DeleteByQueryRequest; import co.elastic.clients.elasticsearch.core.DeleteByQueryResponse; import java.util.Optional; import java.util.concurrent.CompletableFuture; private String deleteLarge(String indexName, Long categoryNumber, Optional<Long> age) { BoolQuery.Builder boolQueryBuilder = QueryBuilders.bool() .filter(f -> f.match(m -> m.field("category").query(categoryNumber))); age.ifPresent(a -> boolQueryBuilder.filter(f -> f.match(m -> m.field("age").query(a)))); DeleteByQueryRequest request = DeleteByQueryRequest.of(d -> d .index(indexName) .query(boolQueryBuilder.build()._toQuery()) .slices(10) .waitForCompletion(false) // 关键参数:设置为false则后台执行任务 ); try { CompletableFuture<DeleteByQueryResponse> future = elasticsearchAsyncClient.deleteByQuery(request); DeleteByQueryResponse response = future.get(); // 仅获取任务提交响应,不等待任务执行完成 String taskId = response.task(); logger.info("DeleteByQueryTask task id: {}", taskId); return taskId; } catch (Exception e) { logger.error(e.getMessage()); } return null; }
当wait_for_completion=false时,ES会立即返回任务ID,任务在后台执行,后续可通过ElasticsearchTasksClient的getTask方法查询任务状态。
3. 若确实无法提交,是否有类似替代方案?使用ElasticsearchAsyncClient的deleteByQuery是否等同于提交任务?
- ElasticsearchAsyncClient的deleteByQuery不等同于默认的后台任务提交:默认情况下,即使是异步客户端调用
deleteByQuery,也会等待任务执行完成后才返回响应,和旧客户端的同步deleteByQuery逻辑一致。只有设置wait_for_completion=false时,才会立即返回任务ID、后台执行任务,这才和原有submitDeleteByQueryTask的效果一致。 - 替代方案:如果需要更灵活的控制,也可以通过滚动查询(Scroll API)批量获取文档ID,再用批量删除(Bulk API)异步执行,但这种方式需要自行管理批量逻辑,不如
deleteByQuery配合wait_for_completion=false简洁高效,尤其适合大量文档的删除场景。
内容的提问来源于stack exchange,提问作者Redwings
相关产品推荐
相关产品推荐

