【问题标题】:How to make elasticsearch add the timestamp field to every document in all indices?如何使elasticsearch将时间戳字段添加到所有索引中的每个文档?
【发布时间】:2013-06-16 17:58:52
【问题描述】:

Elasticsearch 专家,

我一直无法找到一种简单的方法来告诉 ElasticSearch 为添加到所有索引(和所有文档类型)中的所有文档插入 _timestamp 字段。

我看到了特定类型的示例: http://www.elasticsearch.org/guide/reference/mapping/timestamp-field/

还可以查看特定类型的所有索引的示例(使用 _all): http://www.elasticsearch.org/guide/reference/api/admin-indices-put-mapping/

但我无法找到任何有关默认情况下为所有添加的文档添加它的文档,而不管索引和类型如何。

【问题讨论】:

标签: mapping timestamp elasticsearch


【解决方案1】:

Elasticsearch 过去支持自动为被索引的文档添加时间戳,但在 2.0.0 中为 deprecated this feature

从版本 5.5 documentation:

_timestamp 和 _ttl 字段已被弃用,现在已被删除。作为 _timestamp 的替代品,您应该使用应用程序端的当前时间戳填充常规日期字段

【讨论】:

【解决方案2】:

您可以通过在创建索引时提供它来做到这一点。

$curl -XPOST localhost:9200/test -d '{
"settings" : {
    "number_of_shards" : 1
},
"mappings" : {
    "_default_":{
        "_timestamp" : {
            "enabled" : true,
            "store" : true
        }
    }
  }
}'

这将自动为您放入索引中的所有内容创建一个_timestamp。 然后在请求 _timestamp 字段时索引某些内容后,它将被返回。

【讨论】:

  • 这行得通。谢谢马库斯。我认为您不能将其定义为所有索引的全局设置,这是可以的。对于任何想使用 elasticsearch head 插件进行尝试的人,请确保指定 POST 请求而不是 GET。
  • 请记住,_timestamp 必须作为字段请求,以便在查询时返回。添加 {"fields":"_timestamp"}。
  • 另外请注意,如果记录已经写入该索引,则映射将不起作用,因此请务必在将记录写入该索引之前创建映射,否则设置时会出错将类型存储为 true。 -> {"error":"RemoteTransportException[[Damion Hellstrom][inet[/x.x.x.x:y]][indices:admin/mapping/put]]; 嵌套:MergeMappingException[Merge failed with failures {[mapper [_timestamp] 有不同存储值]}]; ","status":400}"
  • 这已被弃用。请谨慎使用。最好是创建自己的日期字段。
  • 这在 7.2 中返回错误:{"error":{"root_cause":[{"type":"mapper_parsing_exception","re​​ason":"根映射定义有不受支持的参数:[默认 : {timestamp={store=true, enabled=true}}]"}],"type":"mapper_parsing_exception","re​​ason":"无法解析映射 [_doc]:根映射定义有不受支持的参数: [_default : {timestamp={store=true, enabled=true}}]","caused_by":{"type":"mapper_parsing_exception","re​​ason":"Root映射定义具有不受支持的参数:[_default : {_timestamp={store=true, enabled=true}}]"}},"status":400}
【解决方案3】:

添加另一种获取索引时间戳的方法。希望这可以帮助某人。

摄取管道可用于在文档被索引时添加时间戳。这是一个示例:

PUT _ingest/pipeline/indexed_at
{
  "description": "Adds indexed_at timestamp to documents",
  "processors": [
    {
      "set": {
        "field": "_source.indexed_at",
        "value": "{{_ingest.timestamp}}"
      }
    }
  ]
}

以前,弹性搜索使用命名管道,因为需要在用于编写/索引文档的弹性搜索端点中指定“管道”参数。 (参考:link)这有点麻烦,因为您需要在应用程序端对端点进行更改。

使用弹性搜索版本 >= 6.5,您现在可以使用 index.default_pipeline 设置为索引指定默认管道。 (详情请参考link

这里是设置默认管道:

PUT ms-test/_settings
{
  "index.default_pipeline": "indexed_at"
}

我还没有尝试过,因为没有升级到 ES 6.5,但是上面的命令应该可以工作。

【讨论】:

    【解决方案4】:

    您可以使用default index pipelines,利用script processor,从而模拟您可能从DjangoDEFAULT GETDATE()SQL 知道的auto_now_add 功能。

    添加默认yyyy-MM-dd HH:mm:ss 日期的过程如下:

    1.创建pipeline 并指定允许在哪些索引上运行:

    PUT _ingest/pipeline/auto_now_add
    {
      "description": "Assigns the current date if not yet present and if the index name is whitelisted",
      "processors": [
        {
          "script": {
            "source": """
              // skip if not whitelisted
              if (![ "myindex",
                     "logs-index",
                     "..."
                  ].contains(ctx['_index'])) { return; }
              
              // don't overwrite if present
              if (ctx['created_at'] != null) { return; }
              
              ctx['created_at'] = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
            """
          }
        }
      ]
    }
    

    旁注:摄取处理器的 Painless 脚本上下文记录在 here

    2。更新所有索引中的default_pipeline 设置:

    PUT _all/_settings
    {
      "index": {
        "default_pipeline": "auto_now_add"
      }
    }
    

    旁注:您可以使用multi-target syntax 限制目标索引:

    PUT myindex,logs-2021-*/_settings?allow_no_indices=true
    {
      "index": {
        "default_pipeline": "auto_now_add"
      }
    }
    

    3.将文档提取到配置的索引之一:

    PUT myindex/_doc/1
    {
      "abc": "def"
    }
    

    4.验证是否已添加日期字符串:

    GET myindex/_search
    

    【讨论】:

    • 这行得通,但 checkif (ctx['created_at'] != null) { return; } 将不起作用,因为 ctx 将不会在下次运行时由处理器创建此属性。
    • 我认为ctx 应该始终存在,但如果不是,您可以另外检查if (ctx != null && ...) 以确保。
    • 所以在我做的测试中,即使ctx != null当你用相同的_id更新一个对象时,你也会得到ctx['created_at']==null。至少,如果我没有做错任何事
    • 您能为此打开另一个 SO 问题吗?不太清楚你的意思。
    • 我明白了。您还应该可以访问 ctx._source 以查看实际的基础值。
    【解决方案5】:

    Python 3 中 ElasticSearch 6.6.2 的示例:

    from elasticsearch import Elasticsearch
    
    es = Elasticsearch(hosts=["localhost"])
    
    timestamp_pipeline_setting = {
      "description": "insert timestamp field for all documents",
      "processors": [
        {
          "set": {
            "field": "ingest_timestamp",
            "value": "{{_ingest.timestamp}}"
          }
        }
      ]
    }
    
    es.ingest.put_pipeline("timestamp_pipeline", timestamp_pipeline_setting)
    
    conf = {
        "settings": {
            "number_of_shards": 2,
            "number_of_replicas": 1,
            "default_pipeline": "timestamp_pipeline"
        },
        "mappings": {
            "articles":{
                "dynamic": "false",
                "_source" : {"enabled" : "true" },
                "properties": {
                    "title": {
                        "type": "text",
                    },
                    "content": {
                        "type": "text",
                    },
                }
            }
        }
    }
    
    response = es.indices.create(
        index="articles_index",
        body=conf,
        ignore=400 # ignore 400 already exists code
    )
    
    print ('\nresponse:', response) 
    
    doc = {
        'title': 'automatically adding a timestamp to documents',
        'content': 'prior to version 5 of Elasticsearch, documents had a metadata field called _timestamp. When enabled, this _timestamp was automatically added to every document. It would tell you the exact time a document had been indexed.',
    }
    res = es.index(index="articles_index", doc_type="articles", id=100001, body=doc)
    print(res)
    
    res = es.get(index="articles_index", doc_type="articles", id=100001)
    print(res)
    

    关于 ES 7.x,该示例在删除 doc_type 相关参数后应该可以工作,因为它不再受支持。

    【讨论】:

      【解决方案6】:

      首先创建索引和索引的属性,例如字段和数据类型,然后使用rest API插入数据。

      以下是使用字段属性创建索引的方法。在kibana控制台中执行以下操作

      `PUT /vfq-jenkins
      {
      "mappings": {
      "properties": {
      "BUILD_NUMBER": { "type" : "double"},
      "BUILD_ID" : { "type" : "double" },
      "JOB_NAME" : { "type" : "text" },
      "JOB_STATUS" : { "type" : "keyword" },
      "time" : { "type" : "date" }
       }}}`    
      

      下一步是将数据插入该索引:

      curl -u elastic:changeme -X POST http://elasticsearch:9200/vfq-jenkins/_doc/?pretty 
      -H Content-Type: application/json -d '{ 
      "BUILD_NUMBER":"83","BUILD_ID":"83","JOB_NAME":"OMS_LOG_ANA","JOB_STATUS":"SUCCESS" , 
      "time" : "2019-09-08'T'12:39:00" }'
      

      【讨论】:

        猜你喜欢
        • 2015-02-16
        • 2018-08-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-20
        • 2021-09-22
        • 1970-01-01
        相关资源
        最近更新 更多