Document  APIs之delete API与Delete by Query API

Delete API

delete API允许根据特定索引的id从索引中删除JSON文档。下面的示例将从id为1的名为twitter的索引中删除JSON文档:

DELETE /twitter/_doc/1
{

    "_shards" : {

        "total" : 2,

        "failed" : 0,

        "successful" : 2

    },

    "_index" : "twitter",

    "_type" : "_doc",

    "_id" : "1",

    "_version" : 2,

    "_primary_term": 1,

    "_seq_no": 5,

    "result": "deleted"

}

Delete操作可以是有条件的,并且只有在为文档的最后修改分配了由if_seq_no和if_primary_term参数指定的序列号和主项时才可以执行。如果检测到不匹配,该操作将导致versionconflict texception和状态代码409。有关详细信息,请参阅乐观并发控制。

版本控制

删除操作和索引操作一样,都有乐观并发控制, 索引的每个文档都有版本。在删除文档时,可以指定版本,以确保我们试图删除的相关文档实际上是被删除的,同时保证删除前它是没有更改的。在文档上执行的每个写操作(包括删除操作)都会使其版本增加。删除后的文档的版本号在短时间内保持可用,以便控制并发操作。已删除文档的版本可用的时间长度由索引设置index.gc_delete,默认值为60秒。

Routing

当索引使用了控制路由的功能时,为了删除文档,还应该提供路由值。例如:

DELETE /twitter/_doc/1?routing=kimchy

将根据用户路由,上面将删除id为1的tweet。注意,在没有正确路由的情况下发出delete将导致文档不被删除。

当_routing映射被设置为required,且没有指定路由值时,delete API将抛RoutingMissingException并拒绝请求。

自动索引创建

如果使用外部版本控制变体,如果之前没有创建索引,delete操作将自动创建索引(查看create index API手动创建索引)

Distributed分布式

delete操作被散列到一个特定的分片id中,然后被重定向到该id组中的主分片中,并被复制(如果需要的话)到该id组中的分片副本中。

等待活动分片

在发出删除请求时,可以设置wait_for_active_shards参数,以要求在开始处理删除请求之前激活最少数量的碎片副本。

Refresh

控制何时可以搜索到此请求所做的更改

Timeout

执行删除操作时,分配用于执行删除操作的主分片可能不可用。原因可能是主分片当前正从存储中恢复或正在进行重定位。默认情况下,delete操作将在主分片上等待最多1分钟,然后失败并响应错误。该timeout参数可用于显式指定等待的时间。以下是将其设置为5分钟的示例:

DELETE /twitter/_doc/1?timeout=5m

Delete By Query API

_delete_by_query最简单的用法就是对每个匹配查询的文档执行删除。以下是API:

POST twitter/_delete_by_query

{

  "query": {                  -------1

    "match": {

      "message": "some message"

    }

  }

}

1: 必须将查询作为值传递给键。,方法与搜索API相同。您还可以像使用搜索API一样使用q参数。

响应:

{

  "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" : [ ]

}

_delete_by_query启动时获取索引的快照,并使用内部版本控制删除它发现的内容。这意味着,如果在捕获快照和处理删除请求之间的文档发生更改,您将会得到版本冲突。当版本匹配时,删除文档。

注意: 由于内部版本控制不支持将值0作为有效版本号,因此不能使用_delete_by_query删除版本为0的文档,并且请求将失败。

在执行_delete_by_query期间,将依次执行多个搜索请求,以便找到要删除的所有匹配文档。每次找到一批文档时,都会执行相应的批量请求来删除所有这些文档。在搜索或批量请求被拒绝的情况下,_delete_by_query依赖于一个默认策略来重试被拒绝的请求(最多10次,呈指数级后退)。达到最大重试限制将导致_delete_by_query中止,所有失败将在响应的失败中返回。已执行的删除操作仍然有效。换句话说,这个过程不是回滚,而是中止。当第一次失败导致中止时,失败的批量请求返回的所有失败将在failure元素中返回;因此,有可能出现相当多的失败实体。

如果您希望计算版本冲突而不是导致它们中止,那么在请求体中设置conflicts=proceed on the url或"conflicts": "proceed"

回到API格式,这将从twitter索引中删除tweet:

POST twitter/_delete_by_query?conflicts=proceed

{

  "query": {

    "match_all": {}

  }

}

也可以一次删除多个索引的文档,就像搜索API一样:

POST twitter,blog/_delete_by_query

{

  "query": {

    "match_all": {}

  }

}

如果提供路由,则将路由复制到滚动查询,将过程限制为匹配该路由值的分片。

POST twitter/_delete_by_query?routing=1

{

  "query": {

    "range" : {

        "age" : {

           "gte" : 10

        }

    }

  }

}

默认情况下,_delete_by_query使用1000的滚动批次。您可以使用scroll_sizeURL参数更改批量大小:

POST twitter/_delete_by_query?scroll_size=5000

{

  "query": {

    "term": {

      "user": "kimchy"

    }

  }

}

URL参数

除了pretty等标准参数之外,delete by query API还支持refresh、wait_for_completion、wait_for_active_shards、timeout和scroll。

发送refresh会刷新所有分片参与delete by query过程,在请求完成时。这与delete API的refresh参数不同的是,后者只会刷新接受删除请求的分片,。同样与delete API不同的是,它不支持wait_for。

如果请求包含wait_for_completion=false,则Elasticsearch将执行一些预检查,启动请求,然后返回一个任务,该任务可与Tasks api一起用于取消或获取任务状态。Elasticsearch还将创建此任务的记录的文档保存到.tasks/task/${taskId}。可以根据你自己的需求进行保留或删除。当完成任务时,删除它,以便Elasticsearch可以回收它使用的空间。

wait_for_active_shards控制在继续请求之前必须有多少个分片必须处于活动状态,详见here 。timeout控制每个写入请求等待不可用分片变成可用的时间。两者都能正确地在Bulk API中工作。由于_delete_by_query使用scroll搜索,您还可以指定scroll参数来控制“搜索上下文”的存活时间,例如?scroll=10m。默认是5分钟。

requests_per_second可以设置为任何正数(1.4,6,1000等),来作为“delete-by-query”每秒请求数的节流阀数字,或者将其设置为-1以禁用限制。节流是在批量批次之间等待,以便它可以操纵滚动超时。等待时间是批次完成的时间除以requests_per_second和写入时间之间的差额。默认的批处理大小是1000,所以如果requests_per_second设置为500:

target_time = 1000 / 500 per second = 2 seconds

wait_time = target_time - write_time = 2 seconds - .5 seconds = 1.5 seconds

由于分批处理没有被分解成多个批量请求,所以会导致Elasticsearch创建许多请求,然后等待一段时间再开始下一组。这是“突发”而不是“平滑”。默认值为-1。

Response body

JSON响应类似如下:

{

  "took" : 147,

  "timed_out": false,

  "total": 119,

  "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,

  "failures" : [ ]

}

took

从整个操作的开始到结束的毫秒数。

timeout

如果在通过查询执行删除期间执行的任何请求超时,则将此标志设置为ture。

Total

已成功处理的文档数。

deleted

成功删除的文档数。

batches

通过查询删除的滚动响应数量。

version_conflicts

根据查询删除时,版本冲突的数量。

noops

对于按查询删除,此字段始终等于零。它只存在,以便通过查询删除,按查询更新和重新索引API返回具有相同结构的响应。

retries

根据查询删除的重试次数。bulk是重试的批量操作的数量,search是重试的搜索操作的数量。

throttled_millis

请求休眠的毫秒数,与`requests_per_second`一致。

requests_per_second

查询删除期间每秒有效执行的请求数。

throttled_until_millis

在_delete_by_query响应中,该字段应该始终等于零。它只有在使用任务API时才有意义,在任务API中,它指示下一次(纪元以毫秒为单位)再次执行节流请求,以符合requests_per_second

failures

如果在此过程中存在任何不可恢复的错误,则会出现故障数组。如果这不是空的,那么请求因为那些失败而中止。使用批处理实现查询删除,任何故障都会导致整个进程中止,但当前批处理中的所有故障都将收集到阵列中。您可以使用该conflicts选项来防止reindex在版本冲突中中止。

配合Task API使用

您可以使用Task API获取任何正在运行的根据查询删除请求的状态:

GET _tasks?detailed=true&actions=*/delete/byquery

响应会类似如下:

{

  "nodes" : {

    "r1A2WoRbTwKZ516z6NEs5A" : {

      "name" : "r1A2WoR",

      "transport_address" : "127.0.0.1:9300",

      "host" : "127.0.0.1",

      "ip" : "127.0.0.1:9300",

      "attributes" : {

        "testattr" : "test",

        "portsfile" : "true"

      },

      "tasks" : {

        "r1A2WoRbTwKZ516z6NEs5A:36619" : {

          "node" : "r1A2WoRbTwKZ516z6NEs5A",

          "id" : 36619,

          "type" : "transport",

          "action" : "indices:data/write/delete/byquery",

          "status" : {                       ------------1

            "total" : 6154,

            "updated" : 0,

            "created" : 0,

            "deleted" : 3500,

            "batches" : 36,

            "version_conflicts" : 0,

            "noops" : 0,

            "retries": 0,

            "throttled_millis": 0

          },

          "description" : ""

        }

      }

    }

  }

}

① 此对象包含实际状态。它就像是响应json,重要的添加total字段。 total是重建索引希望执行的操作总数。您可以通过添加的updated、created和deleted的字段来估计进度。当它们的总和等于total字段时,请求将完成。

使用任务id可以直接查找任务:

GET /_tasks/r1A2WoRbTwKZ516z6NEs5A:36619

这个API的优点是它与wait_for_completion=false集成,以透明地返回已完成任务的状态。如果任务完成并且wait_for_completion=false被设置,那么它将返回results或error字段。此功能的成本是wait_for_completion=false在.tasks/task/${taskId}创建的文档,你可以删除该文档。

配合取消任务API使用

所有根据查询删除都能使用Task Cancel API取消:

POST _tasks/r1A2WoRbTwKZ516z6NEs5A:36619/_cancel

可以使用上面的任务API找到task_id。 取消正常会很快发生,但可能需要几秒钟。上面的任务状态API将继续列出delete by query任务,直到此任务检查它已被取消并终止自身。。

重置节流阀

request_per_second的值可以在通过查询删除时使用_rethrottle API更改:

POST _delete_by_query/task_id:1/_rethrottle?requests_per_second=-1

可以使用上面的任务API找到task_id。

就像在_delete_by_query API中设置它一样,request_per_second可以是-1来禁用限制,或者任何十进制数字,如1.7或12,以节制到该级别。加快查询速度的Rethrottling将立即生效,但是减慢查询速度的Rethrottling将在完成当前批处理后生效。这可以防止滚动超时。

Slicing

按查询删除支持滚动切分以并行化删除过程。这种并行化可以提高效率,并提供一种方便的方法将请求分解为更小的部分。

手动Slicing

通过为每个请求提供Slicing id和切分总数,手动切分查询删除:

POST twitter/_delete_by_query

{

  "slice": {

    "id": 0,

    "max": 2

  },

  "query": {

    "range": {

      "likes": {

        "lt": 10

      }

    }

  }

}
POST twitter/_delete_by_query

{

  "slice": {

    "id": 1,

    "max": 2

  },

  "query": {

    "range": {

      "likes": {

        "lt": 10

      }

    }

  }

}

您可以通过以下方式验证:

GET _refresh
POST twitter/_search?size=0&filter_path=hits.total

{

  "query": {

    "range": {

      "likes": {

        "lt": 10

      }

    }

  }

}

其结果一个合理的total像这样:

{

  "hits": {

    "total" : {

        "value": 0,

        "relation": "eq"

    }

  }

}

自动切片

你还可以让根据delete-by-query自动并行使用sliced scroll去切分在_id上 。使用slices指定使用的数字来确定切分数量。

POST twitter/_delete_by_query?refresh&slices=5

{

  "query": {

    "range": {

      "likes": {

        "lt": 10

      }

    }

  }

}

您可以通过以下方式验证:

POST twitter/_search?size=0&filter_path=hits.total

{

  "query": {

    "range": {

      "likes": {

        "lt": 10

      }

    }

  }

}

其结果一个合理的total像这样:

{

  "hits": {

    "total" : {

        "value": 0,

        "relation": "eq"

    }

  }

}

将切片设置为auto将让Elasticsearch选择要使用的切片数量。此设置将在一定限度内使用每个分片一个切分。如果有多个源索引,它将根据碎片数量最少的索引选择切片的数量

将slices添加到_delete_by_query中可以自动执行上述部分中使用的手动过程,创建子请求,这意味着它有一些怪癖:

  • 您可以在Task API中看到这些请求。这些子请求是具有slices请求任务的“子”任务。
  • 获取slices请求任务的状态只包含已完成切分的状态。
  • 这些子请求可以单独寻址,例如取消和重置节流阀。
  • slices的重置节流阀请求将按相应的重新计算未完成的子请求。
  • slices的取消请求将取消每个子请求。
  • 由于slices的性质,每个子请求将不会获得完全均匀的文档部分。所有文件都将被处理,但有些片可能比其他片大。预期更大的切分可以有更均匀的分布。
  • 带有slices请求的request_per_second和size的参数相应的分配给每个子请求。结合上述关于分布的不均匀性,您应该得出结论,使用切分大小可能不会导致正确的大小文档为_delete_by_query。
  • 每个子请求都会获得源索引的略有不同的快照,尽管这些都是大致相同的时间。

挑选切分数量

如果自动切分,设置slices为auto将为大多数索引选择合理的数字。如果您手动切片或以其他方式调整自动切片,请使用这些指南。

当数量slices等于索引中的分片数时,查询性能最有效。如果该数字很大(例如,500),请选择较小的数字,因为太多slices会损害性能。设置 slices高于分片数通常不会提高效率并增加开销。

删除性能在可用资源上以切片数量线性扩展。

查询或删除性能是否主导运行时取决于重新编制索引的文档和群集资源。

<!DOCTYPE html> <html> <head> <title>查询和删除功能</title> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> </head> <body> <h1>查询和删除</h1> <form> <label for="queryInput">查询:</label> <input type="text" id="queryInput" name="queryInput"> <button onclick="query()">查询</button> </form> <form> <label for="deleteInput">删除:</label> <input type="text" id="deleteInput" name="deleteInput"> <button onclick="deleteItem()">删除</button> </form> <div id="result"></div> <script src="script.js"></script> </body> </html> ``` script.js: ```javascript function query() { var queryValue = document.getElementById("queryInput").value; $.ajax({ url: "/query", method: "GET", data: { query: queryValue }, success: function(response) { document.getElementById("result").innerText = response; }, error: function(xhr, status, error) { console.error(error); } }); } function deleteItem() { var deleteValue = document.getElementById("deleteInput").value; $.ajax({ url: "/delete", method: "DELETE", data: { delete: deleteValue }, success: function(response) { document.getElementById("result").innerText = response; }, error: function(xhr, status, error) { console.error(error); } }); } ``` server.js: ```javascript const express = require('express'); const bodyParser = require('body-parser'); const app = express(); app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json()); app.get('/query', (req, res) => { const queryValue = req.query.query; const result = `查询成功,结果为:${queryValue}`; res.send(result); }); app.delete('/delete', (req, res) => { const deleteValue = req.body.delete; const result = `删除成功:${deleteValue}`;
07-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值