Elasticsearch:使用groovy脚本转换日期

时间:2015-08-05 12:21:21

标签: groovy elasticsearch

我有以下(简化)映射:

{
  "event_date": {
    "_source": { "enabled": true },
    "_all": { "enabled": true },
    "dynamic": "strict",
    "properties": {
      "start_date_time": {
        "type": "date",
        "format": "dateOptionalTime"
      },
      "start_date_day": {
        "type": "date",
        "format": "dateOptionalTime",
        "index": "not_analyzed"
      }
    }
  }
}

索引对象将如下所示:

{
  "start_date_time": "2017-05-08T18:23:45+0200"
}

属性start_date_day应始终包含相同的日期,但时间设置为00:00:00。在上面的示例中,start_date_day必须为“2017-05-08T00:00:00 + 0200”。

我认为,使用transform mapping和groovy脚本可以实现这一点,但是我开发的groovy代码在elasticsearch-context中不起作用,而且我对groovy语言并不熟悉。

也许有人知道如何解决这个问题?

3 个答案:

答案 0 :(得分:3)

是的,这是可行的,为了测试/运行,您可能需要先在script.groovy.sandbox.enabled: true中启用../conf/elasticsearch.yml

PUT datetest/
{
    "mappings": {
        "event_date": {
            "_source": { "enabled": true },
            "_all": { "enabled": true },
            "dynamic": "strict",
            "transform" : {
                "script" : "ctx._source['start_date_day'] = new Date().parse(\"yyyy-MM-dd\", ctx._source['start_date_time']).format(\"yyyy-MM-dd\");",
                "lang": "groovy"
            },
            "properties": {
                "start_date_time": {
                    "type": "date",
                    "format": "dateOptionalTime"
                },
                "start_date_day": {
                    "type": "date",
                    "format": "dateOptionalTime",
                    "index": "not_analyzed",
                    "store": "yes"
                }
            }
        }
    }
}

示例数据:

PUT /datetest/event_date/1
{
  "start_date_time": "2017-05-08T18:23:45+0200"
}

示例输出:

GET /datetest/event_date/_search
{
  "query": {
    "match_all": {}
  },
  "fields": ["start_date_time","start_date_day"]
}

{
   "took": 2,
   "timed_out": false,
   "_shards": {
      "total": 5,
      "successful": 5,
      "failed": 0
   },
   "hits": {
      "total": 1,
      "max_score": 1,
      "hits": [
         {
            "_index": "datetest",
            "_type": "event_date",
            "_id": "1",
            "_score": 1,
            "fields": {
               "start_date_day": [
                  "2017-05-08T00:00:00.000Z"
               ],
               "start_date_time": [
                  "2017-05-08T18:23:45+0200"
               ]
            }
         }
      ]
   }
}

答案 1 :(得分:1)

我认为这种格式并不好。 “日期”似乎是MM / DD / YYYY,只有这一点。如果您想要时间,则需要日期时间格式。 我找到了这个可以帮助您的链接:Elastic date format

您可以尝试将“date”类型更改为“basic_date_time”。

答案 2 :(得分:1)

根据您的评论,由于您不需要小时部分,因此您只需使用date format定义start_date_day字段的映射,并使用以下transform

{
  "event_date": {
    "_source": {
      "enabled": true
    },
    "_all": {
      "enabled": true
    },
    "dynamic": "strict",
    "transform": {
      "script": "ctx._source['start_date_day'] = ctx._source['start_date_time'].split('T')[0]",
      "lang": "groovy"
    },
    "properties": {
      "start_date_time": {
        "type": "date",
        "format": "dateOptionalTime"
      },
      "start_date_day": {
        "type": "date",
        "format": "date",
        "index": "not_analyzed"
      }
    }
  }
}

ES只会存储日期部分并将小时和时区保留。

但是,您应该注意,使用transform时,原始源将被存储而不进行修改,但转换的结果将被编入索引,因此可以搜索。

相关问题