如何通过Elasticsearch Java API记录DeleteByQuery处理/删除的所有文档?
记录DeleteByQuery处理/删除的具体文档
要获取DeleteByQuery操作中所有被处理/删除的具体文档信息,需要调整请求配置并遍历响应结果,以下是两种可行方案:
方案一:直接通过DeleteByQueryResponse获取文档信息
通过配置DeleteByQueryRequest开启源数据获取,执行后遍历响应中的每个操作项,即可拿到单个文档的详情:
步骤1:配置DeleteByQueryRequest
// 创建删除请求,指定目标索引 DeleteByQueryRequest deleteRequest = new DeleteByQueryRequest("your_target_index"); // 设置删除的查询条件,这里以匹配所有文档为例 deleteRequest.setQuery(QueryBuilders.matchAllQuery()); // 开启获取文档源数据,可指定需要返回的字段(第一个参数为包含字段,第二个为排除字段) deleteRequest.setFetchSource(new String[]{"_id", "name", "create_time"}, null);
步骤2:执行请求并遍历结果
BulkByScrollResponse bulkResponse = client.deleteByQuery(deleteRequest, RequestOptions.DEFAULT); // 遍历所有被处理的文档 for (BulkItemResponse item : bulkResponse.getItems()) { String docIndex = item.getIndex(); String docId = item.getId(); if (item.isFailed()) { // 处理文档操作失败的情况 BulkItemResponse.Failure failure = item.getFailure(); System.out.printf("文档处理失败 - 索引: %s, ID: %s, 原因: %s%n", docIndex, docId, failure.getMessage()); continue; } // 获取文档源数据(需提前开启fetchSource) Map<String, Object> docSource = item.getResponse().getGetResult().getSource(); // 判断操作类型是否为删除 boolean isDeleted = item.getOpType() == DocWriteRequest.OpType.DELETE; System.out.printf("已处理文档 - 索引: %s, ID: %s, 操作类型: %s, 源数据: %s%n", docIndex, docId, isDeleted ? "删除" : "其他", docSource); } // 保留总数统计 System.out.println("Total documents processed: " + bulkResponse.getTotal()); System.out.println("Total documents deleted: " + bulkResponse.getDeleted());
注意:如果文档数据量较大,返回完整源数据会占用较多内存,建议仅指定业务需要的字段,避免性能问题。
方案二:先查询记录再执行删除
如果需要先完整记录待删除文档信息,再执行删除操作,可以通过Scroll查询先获取所有待删文档,再批量删除:
步骤1:Scroll查询待删除文档并记录
// 创建查询请求 SearchRequest searchRequest = new SearchRequest("your_target_index"); SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); // 设置与DeleteByQuery一致的查询条件 sourceBuilder.query(QueryBuilders.matchAllQuery()); sourceBuilder.size(1000); // 每次Scroll拉取的文档数量 searchRequest.source(sourceBuilder); searchRequest.scroll(TimeValue.timeValueMinutes(1)); // 设置Scroll有效期 SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); String scrollId = searchResponse.getScrollId(); SearchHit[] hits = searchResponse.getHits().getHits(); List<String> toDeleteDocIds = new ArrayList<>(); // 遍历所有Scroll结果 while (hits != null && hits.length > 0) { for (SearchHit hit : hits) { String docIndex = hit.getIndex(); String docId = hit.getId(); Map<String, Object> docSource = hit.getSourceAsMap(); System.out.printf("待删除文档 - 索引: %s, ID: %s, 源数据: %s%n", docIndex, docId, docSource); toDeleteDocIds.add(docId); } // 续拉取下一批数据 SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId); scrollRequest.scroll(TimeValue.timeValueMinutes(1)); searchResponse = client.scroll(scrollRequest, RequestOptions.DEFAULT); scrollId = searchResponse.getScrollId(); hits = searchResponse.getHits().getHits(); } // 清理Scroll上下文,释放资源 ClearScrollRequest clearScrollRequest = new ClearScrollRequest(); clearScrollRequest.addScrollId(scrollId); client.clearScroll(clearScrollRequest, RequestOptions.DEFAULT);
步骤2:执行批量删除
DeleteByQueryRequest deleteRequest = new DeleteByQueryRequest("your_target_index"); // 根据记录的ID执行删除 deleteRequest.setQuery(QueryBuilders.idsQuery().addIds(toDeleteDocIds.toArray(new String[0]))); BulkByScrollResponse bulkResponse = client.deleteByQuery(deleteRequest, RequestOptions.DEFAULT); System.out.println("Total documents deleted: " + bulkResponse.getDeleted());
这种方案更适合需要在删除前做数据校验、备份的场景,同时避免大数量下DeleteByQuery返回过多数据的性能问题。
内容的提问来源于stack exchange,提问作者KiKo
相关产品推荐
相关产品推荐

