记录关于Elasticsearch的文档删除API的学习


首先官网上Document APIs介绍了 Delete API 和Delete By Query API。


Delete API

可以通过指定索引–>类型–>id的方式对文档进行删除


DELETE /index/type/1

1

响应body


{

    "_shards" : {

        "total" : 2,

        "failed" : 0,

        "successful" : 2

    },

    "found" : true,

    "_index" : "index",

    "_type" : "type",

    "_id" : "1",

    "_version" : 2,

    "result": "deleted"

}


Versioning

每个文档都会对应一个版本,当我们执行删除操作时,版本号也要指定。来确保执行删除时,没有同时执行写入操作。不论是写入操作还是删除操作,都会对文档的版本进行更改。所以当我们使用这个Delete API删除文档时,并不是真正意义上的删除,只是版本变化并且对文档增加了删除标记。当我们再次搜索的时候,会搜索全部然后过滤掉有删除标记的文档。如果数据量大的话,对搜索的性能有一定的影响。必须对它进行物理删除。


物理删除方法:

谈到物理删除,就是把删除的文档信息从磁盘空间中去掉。还需要了解Elasticsearch官方文档的Indices APIs的Indices Segments。


Indeices Segments(段)

它是用于构建Lucene索引(碎片级)的低级段信息,提供关于碎片和索引状态的更多信息,可能是优化信息、删除时“浪费”的数据等等。


Segments有一个关于删除文档的重要属性就是,被标记删除的文档存储在Segment中。如果这个数量大于0是完全可以的,那么在合并这个segment 时将回收空间。


因此如果我们想进行物理删除,必须进行段合并。理论上是Elasticsearch会自己进行段合并,但是合并的数量随机,很难保证将标记删除的文档的段进行合并。因此需要进行配置。


Delete By Query API

除了指定删除之外,官网还提供了根据查询条件进行文档删除。


POST twitter/_delete_by_query

{

  "query": {

    "match": {

      "message": "some message"

    }

  }

}


请求体跟Search API是一样的


响应Body


{

  "took" : 147,

  "timed_out": false,

  "deleted": 119,

  "batches": 1,

  "version_conflicts": 0,

  "noops": 0,

  "retries": {

    "bulk": 0,

    "search": 0

  },

  "throttled_millis": 0,

  "requests_per_second": -1.0,

  "throttled_until_millis": 0,

  "total": 119,

  "failures" : [ ]

}


应用实例:

学习过删除文档操作之后,就要进行应用啦。由于项目是使用java,对Elasticsearch文档进行操作的。因此要对Elasticsearch Client进行选型。TransportClient迟早要gg,因此果断选择java REST Client(优点:1.可以使用TransportClient功能 2.可以向前兼容Elasticsearch版本集群)。但是在REST Client 6.5之前,官网是没有对Delete By Query API进行介绍的,也就是说想使用按照搜索方式删除文档,需要借助TransportClient。这里我们可以直接使用REST Client 6.5


REST Client ----Delete By Query API

代码:


//创建客户端

RestHighLevelClient client = new RestHighLevelClient(

                RestClient.builder(new HttpHost("192.168.XXX.XX", 9200, "http"))

                .setMaxRetryTimeoutMillis(X * 60 * 1000) //超时时间设为X分钟

                );

//查询要删除的文档

DeleteByQueryRequest deleteByQueryRequest = new DeleteByQueryRequest("_all");

deleteByQueryRequest.setConflicts("proceed");        

request.setQuery(new TermQueryBuilder("user", "kimchy"));

deleteByQueryRequest.setSize(size);

BulkByScrollResponse bulkResponse = client.deleteByQuery(deleteByQueryRequest, RequestOptions.DEFAULT);

//合并段,进行物理删除

ForceMergeRequest requestAll = new ForceMergeRequest();

requestAll.maxNumSegments(1);

requestAll.onlyExpungeDeletes(true);

ForceMergeResponse forceMergeResponse = client.indices().forcemerge(requestAll, RequestOptions.DEFAULT);

1


参考:


[1] https://www.elastic.co/guide/en/elasticsearch/reference/5.6/docs-delete.html elasticsearch5.6官网

[2] https://www.elastic.co/guide/en/elasticsearch/reference/5.6/indices-forcemerge.html elasticsearch5.6官网

[3] https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-document-delete-by-query.html REST Client 6.5 delete by query


[4] https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-force-merge.html

REST Client 6.5 段合并


梅花香自古寒来