簡體   English   中英

使用 Python 批量更新 elasticsearch 文檔

[英]Bulk Update for elasticsearch documents using Python

我有 elasticsearch 文檔,如下所示,我需要根據創建時間currentdate更正年齡

年齡 = 創建時間 - 當前日期

hits = [
   {
      "_id":"CrRvuvcC_uqfwo-WSwLi",
      "creationtime":"2018-05-20T20:57:02",
      "currentdate":"2021-02-05 00:00:00",
      "age":"60 months"
   },
   {
      "_id":"CrRvuvcC_uqfwo-WSwLi",
      "creationtime":"2013-07-20T20:57:02",
      "currentdate":"2021-02-05 00:00:00",
      "age":"60 months"
   },
   {
      "_id":"CrRvuvcC_uqfwo-WSwLi",
      "creationtime":"2014-08-20T20:57:02",
      "currentdate":"2021-02-05 00:00:00",
      "age":"60 months"
   },
   {
      "_id":"CrRvuvcC_uqfwo-WSwLi",
      "creationtime":"2015-09-20T20:57:02",
      "currentdate":"2021-02-05 00:00:00",
      "age":"60 months"
   }
]

我想根據每個文檔 ID 進行批量更新,但問題是我需要更正 6 個月的數據並且每個數據大小(索引的文檔計數)幾乎是535329 ,我想有效地根據_id年齡進行批量更新對於使用 python 的所有文檔的每一天。

有沒有辦法做到這一點,而無需循環,我遇到的所有使用 Pandas 數據幀進行更新的示例都基於已知值。 但是在這里_id我會在代碼運行時得到。

我編寫的邏輯是獲取所有文檔並存儲它們的_id ,然后為每個_id更新年齡 但如果我想在 6 個月的每一天批量更新所有文檔,這不是一種有效的方法。

誰能給我一些想法或指出正確的方向。

如評論中所述,無需獲取 ID。 您甚至不需要自己獲取文件!

一個_update_by_query調用就足夠了。 解析日期后,您可以使用ChronoUnit來獲得差異:

POST your-index-name/_update_by_query
{
  "query": {
    "match_all": {}
  },
  "script": {
    "source": """
      def created =  LocalDateTime.parse(ctx._source.creationtime, DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss"));

      def currentdate = LocalDateTime.parse(ctx._source.currentdate, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    
      def months = ChronoUnit.MONTHS.between(created, currentdate);
      ctx._source._age = months + ' month' + (months > 1 ? 's' : '');
    """,
    "lang": "painless"
  }
}

python 官方客戶端也有這個方法 這是一個工作示例

嘗試在文檔的一小部分上運行此更新腳本,然后通過添加除我放在那里的match_all之外的查詢來釋放整個索引。


值得一提的是,除非你在這個age字段上進行搜索,否則它不需要存儲在你的索引中,因為它可以在查詢時計算出來。

你看,如果你的索引映射的日期是這樣正確定義的:

{
  "mappings": {
    "properties": {
      "creationtime": {
        "type": "date",
        "format": "yyyy-MM-dd'T'HH:mm:ss"
      },
      "currentdate": {
        "type": "date",
        "format": "yyyy-MM-dd HH:mm:ss"
      },
      ...
    }
  }
}

age可以計算為腳本字段

POST ttimes/_search
{
  "query": {
    "match_all": {}
  },
  "script_fields": {
    "age_calculated": {
      "script": {
        "source": """
          def months = ChronoUnit.MONTHS.between(
                          doc['creationtime'].value,
                          doc['currentdate'].value );
          return months + ' month' + (months > 1 ? 's' : '');
        """
      }
    }
  }
}

唯一需要注意的是,該值不會在_source內,而是在其自己的稱為fields的組內(這意味着一次可能有更多腳本字段。)。

"hits" : [
  {
    ...
    "_id" : "FFfPuncBly0XYOUcdIs5",
    "fields" : {
      "age_calculated" : [ "32 months" ]   <--
    }
  },
  ...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM