Elasticsearch按查询版本冲突删除

时间:2019-05-14 19:31:34

标签: elasticsearch

我正在使用Elasticsearch 5.6.10版本。我有一个查询,该查询删除给定代理商的记录,因此以后可以通过每晚脚本更新它们。

查询位于elasticsearch-dsl中,如下所示:

def remove_employees_from_search(jurisdiction_slug, year):
    s = EmployeeDocument.search()
    s = s.filter('term', year=year)
    s = s.query('nested', path='jurisdiction', query=Q("term", **{'jurisdiction.slug': jurisdiction_slug}))
    response = s.delete()
    return response

问题是尝试通过该函数删除记录时遇到了ConflictError异常。我已经读过这种情况是因为删除操作开始和执行之间的文档不同。但是我不知道怎么回事,因为在删除过程中,没有其他东西可以修改记录。

我要添加s = s.params(conflicts='proceed')以便使异常保持沉默。但这是一个创可贴,因为我不明白为什么删除未按预期进行。关于如何解决此问题的任何想法?错误快照如下:

ConflictError:TransportError(409,
u'{  
   "took":10,
   "timed_out":false,
   "total":55,
   "deleted":0,
   "batches":1,
   "version_conflicts":55,
   "noops":0,
   "retries":{  
      "bulk":0,
      "search":0
   },
   "throttled_millis":0,
   "requests_per_second":-1.0,
   "throttled_until_millis":0,
   "failures":[  
      {  
         "index":"employees",
         "type":"employee_document",
         "id":"24681043",
         "cause":{  
            "type":"version_conflict_engine_exception",
            "reason":"[employee_document][24681043]: version conflict, current version [5] is different than the one provided [4]",
            "index_uuid":"G1QPF-wcRUOCLhubdSpqYQ",
            "shard":"0",
            "index":"employees"
         },
         "status":409
      },
      {  
         "index":"employees",
         "type":"employee_document",
         "id":"24681063",
         "cause":{  
            "type":"version_conflict_engine_exception",
            "reason":"[employee_document][24681063]: version conflict, current version [5] is different than the one provided [4]",
            "index_uuid":"G1QPF-wcRUOCLhubdSpqYQ",
            "shard":"0",
            "index":"employees"
         },
         "status":409
      }

1 个答案:

答案 0 :(得分:0)

首先,这是一个 2 年前提出的问题,因此由于时间间隔,请保留我的回答。

我使用的是 javascript API,但我敢打赌这些标志是相似的。当您使用 indexdelete 时,有一个 refresh 标志,它允许您强制索引显示搜索结果。

我不是 Elasticsearch 专家,但引擎必须对索引和分片进行一些系统的维护,以便将索引移动到稳定状态。它可能随着时间的推移而完成,因此您不一定会立即获得状态更新。此外,根据个人经验,我看到 delete 似乎没有从索引中删除项目。它可能会将其标记为“已删除”,为文档提供一个新的版本号,但它似乎“一直存在”(可能直到运行一般维护扫描)。

这里我展示了 delete 的 js API,但 index 和其他一些调用是一样的。

client.delete({
  id: string,
  index: string,
  type: string,
  wait_for_active_shards: string,
  refresh: 'true' | 'false' | 'wait_for',
  routing: string,
  timeout: string,
  if_seq_no: number,
  if_primary_term: number,
  version: number,
  version_type: 'internal' | 'external' | 'external_gte' | 'force'
})

https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/api-reference.html#_delete

<块引用>

刷新 '真' | '假' | 'wait_for' - 如果为 true,则刷新受影响的分片以使此操作对搜索可见,如果为 wait_for,则等待刷新以使此操作对搜索可见,如果为 false(默认值)则不执行任何刷新操作。

作为额外的参考,这里是关于 Elasticsearch 刷新信息的页面,以及对你来说可能相当相关的简介。 https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-refresh.html

<块引用>

使用刷新 API 显式刷新一个或多个索引。如果请求以数据流为目标,它会刷新流的支持索引。刷新使自上次刷新以来对索引执行的所有操作都可用于搜索。

<块引用>

默认情况下,Elasticsearch 每秒定期刷新索引,但仅限于在过去 30 秒内收到一个或多个搜索请求的索引。您可以使用 index.refresh_interval 设置更改此默认间隔.