You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 04:41:00