Elasticsearch(七)--ES文档的操作(下)---删除文档

一、前言

上篇文章我们了解了ES的修改文档的操作,也同样分别通过ES的kibana客户端以及Java高级Rest客户端进行学习,那么本篇末尾要给大家介绍的是对文档的删除操作,同新修改文档,也有删除单条文档和批量删除文档操作,根据条件删除文档,我们本篇均会涉及到。

二、删除文档

2.1、删除单条文档

在ES中删除文档的请求的类型是DELETE,其请求的形式如下:

DELETE /${index_name}/_doc/${_id}

上面的_id就是将要删除的ES文档的_id。执行下面的删除命令:

DELETE /hotel/_doc/021

返回的结果如下:
Elasticsearch(七)--ES文档的操作(下)---删除文档_第1张图片
通过结果可知,已经成功删除文档,之前添加的文档已经不存在了。我们可以通过下面的根据_id搜索文档的命令进行验证:

GET /hotel/_doc/021

ES返回结果如下:
Elasticsearch(七)--ES文档的操作(下)---删除文档_第2张图片
由返回的结果可知,删除已经生效。
在Java高级REST客户端中,执行删除文档需要创建DeleteRequest对象并设置对应的索引名称和删除文档的_id,然后执行客户端的delete()方法并把DeleteRequest对象传入即可。以下代码演示了根据_id删除文档的方法。
首先同修改一样,我们需要建立一个专门处理删除逻辑的service,记得引入client:

public String singleDelete(String indexName, String docId) {
		if (CharSequenceUtil.isBlank(indexName)) {
			throw new SearchException("索引名不能为空");
		}
		DeleteRequest deleteRequest = new DeleteRequest(indexName, docId);
		try {
			DeleteResponse deleteResponse = client.delete(deleteRequest, RequestOptions.DEFAULT);
			return deleteResponse.toString();
		} catch (IOException e) {
			throw new SearchException("删除服务错误");
		}
	}

接着controller层调用service:

    @PostMapping("/single/delete")
	public FoundationResponse<String> singleDelete(String indexName, String docId) {
		try {
			String result = esDeleteDocService.singleDelete(indexName, docId);
			return FoundationResponse.success(result);
		} catch (SearchException e) {
			log.warn("搜索发生异常,原因为:{}", e.getMessage());
			return FoundationResponse.error(100, e.getMessage());
		} catch (Exception e) {
			log.error("服务发生异常,原因为:{}", e.getMessage());
			return FoundationResponse.error(100, e.getMessage());
		}
	}

然后postman调用该接口:
Elasticsearch(七)--ES文档的操作(下)---删除文档_第3张图片

2.2、批量删除文档

与批量写入和更新文档不同的是,批量删除文档不需要提供JSON数据,其请求形式如下:

POST /_bulk
{"delete":{"_index":"${index_name}","_id":"${_id}"}}
{"delete":{"_index":"${index_name}","_id":"${_id}"}}

例如,下面的DSL将批量删除_id为002,003,004的文档:

POST /_bulk
{"delete":{"_index":"hotel_order","_id":"004"}}
{"delete":{"_index":"hotel_order","_id":"002"}}
{"delete":{"_index":"hotel_order","_id":"003"}}

和批量写入修改文档相似,在Java客户端接口中,批量删除文档同样需要创建BulkRequest对象并设置对应的索引名称。对于多条需要删除的文档,可构建多个DeleteRequest对象并调用BulkRequest.add()方法添加这些DeleteRequest对象,执行时,调用客户端的bulk()方法并把BulkRequest对象传入即可。
首先Service层代码如下,我们通过接收前端传的需要批量删除的id的list进行批量删除,并且模拟的是删除同一个索引下的多个文档:

public String bulkDelete(HotelDocRequest hotelDocRequest) {
		String indexName = hotelDocRequest.getIndexName();
		if (CharSequenceUtil.isBlank(indexName)) {
			throw new SearchException("索引名不能为空");
		}
		List<String> docIds = hotelDocRequest.getHotelList().stream().map(Hotel::getId).collect(Collectors.toList());
		BulkRequest bulkRequest = new BulkRequest();
		for (String docId : docIds) {
	        //创建DeleteRequest
			DeleteRequest deleteRequest = new DeleteRequest(indexName, docId);
			bulkRequest.add(deleteRequest);
		}
		BulkResponse bulkResponse;
		try {
		    //执行批量删除
			bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT);
			if (bulkResponse.hasFailures()) {
				return "失败,原因:" + bulkResponse.buildFailureMessage();
			} else {
				return "成功";
			}
		} catch (IOException e) {
			throw new SearchException("批量修改服务错误");
		}
	}

controller调用Service层:

    @PostMapping("/bulk/delete/doc")
	public FoundationResponse<String> bulkDelete(@RequestBody HotelDocRequest hotelDocRequest) {
		List<Hotel> hotelList = hotelDocRequest.getHotelList();
		if (CollUtil.isEmpty(hotelList)) {
			return FoundationResponse.error(100, "无可修改的有效文档");
		}
		try {
			String s = esDeleteDocService.bulkDelete(hotelDocRequest);
			return FoundationResponse.success(s);
		} catch (SearchException e) {
			log.warn("批量删除发生异常,原因为:{}", e.getMessage());
			return FoundationResponse.error(100, e.getMessage());
		} catch (Exception e) {
			log.error("服务发生异常,原因为:{}", e.getMessage());
			return FoundationResponse.error(100, e.getMessage());
		}
	}

postman调用该接口,body如下:

{
    "hotelList": [
        {
            "id": "001"
        },
        {
            "id": "002"
        }
    ],
    "indexName":"hotel"
}

返回结果如下:
Elasticsearch(七)--ES文档的操作(下)---删除文档_第4张图片

2.3、根据条件删除文档

和条件更新操作类似,有些场景需要根据某些条件同时删除多条数据,类似于在关系型数据库中使用delete table_name where… 删除一批数据。为了满足这样的需求,ES为用户提供了_delete_by_query功能,其请求形式如下:

POST /hotel/_delete_by_query
{
  "query":{
      ...  //删除文档的查询条件
  }
}

query子句用于指定删除数据的匹配条件,相当于SQL中的where语句。下面的DSL将把city为成都的文档删除:

POST /hotel/_delete_by_query
{
  "query":{
    "term":{
      "city":{
        "value":"成都"
      }
    }
  }
}

在java高级REST客户端中,执行条件删除文档需要创建DeleteByQueryRequest对象并设置对应的索引名称类似于DSL中的query子句,通过调用DeleteByQueryRequest.setQuery()方法设置查询逻辑,然后执行客户端的deleteByQuery()方法并把DeleteByQueryRequest对象传入即可。以下代码演示了根据城市删除文档的方法:
Service层:

public String deleteByCity(String indexName, String city) {
		DeleteByQueryRequest deleteByQueryRequest = new DeleteByQueryRequest(indexName);
		deleteByQueryRequest.setQuery(new TermQueryBuilder("city", city));
		try {
			BulkByScrollResponse response = client.deleteByQuery(deleteByQueryRequest, RequestOptions.DEFAULT);
			return response.toString();
		} catch (IOException e) {
			throw new SearchException("按照条件修改服务错误");
		}
	}

controller调用service:

	@PostMapping("/delete/byCity")
	public FoundationResponse<String> updatePriceByQueryCity(String indexName, String city) {
		if (CharSequenceUtil.isBlank(indexName)) {
			throw new SearchException("索引名不能为空");
		}
		try {
			String result = esDeleteDocService.deleteByCity(indexName, city);
			return FoundationResponse.success(result);
		} catch (SearchException e) {
			log.warn("搜索发生异常,原因为:{}", e.getMessage());
			return FoundationResponse.error(100, e.getMessage());
		} catch (Exception e) {
			log.error("服务发生异常,原因为:{}", e.getMessage());
			return FoundationResponse.error(100, e.getMessage());
		}
	}

postman调用该接口:
Elasticsearch(七)--ES文档的操作(下)---删除文档_第5张图片

你可能感兴趣的:(elasticsearch,elasticsearch,java,spring,boot)