在弹性搜索查询中格式化日期(检索期间)
Format date in elasticsearch query (during retrieval)
我有一个 elasticsearch 索引,其中一个字段 "aDate"(以及许多其他字段)具有以下映射
"aDate" : {
"type" : "date",
"format" : "date_optional_time"
}
当我查询文档时,我得到的结果类似于
"aDate" : 1421179734000,
我知道这是纪元,内部 java/elasticsearch 日期格式,但我想要这样的结果:
"aDate" : "2015-01-13T20:08:54",
我玩脚本
{
"query":{
"match_all":{
}
},
"script_fields":{
"aDate":{
"script":"if (!_source.aDate?.equals('null')) new java.text.SimpleDateFormat('yyyy-MM-dd\'T\'HH:mm:ss').format(new java.util.Date(_source.aDate));"
}
}
}
但它给出了奇怪的结果(脚本基本上可以工作,但 aDate 是唯一返回的字段并且缺少 _source)。这看起来像
"hits": [{
"_index": "idx1",
"_type": "type2",
"_id": "8770",
"_score": 1.0,
"fields": {
"aDate": ["2015-01-12T17:15:47"]
}
},
如果可能的话,我更喜欢没有脚本的解决方案。
当您在 Elasticsearch 中 运行 查询时,您可以请求它 return 原始数据,例如指定 fields:
curl -XGET http://localhost:9200/myindex/date-test/_search?pretty -d '
{
"fields" : "aDate",
"query":{
"match_all":{
}
}
}'
将以您最初存储的格式为您提供日期:
{
"_index" : "myindex",
"_type" : "date-test",
"_id" : "AUrlWNTAk1DYhbTcL2xO",
"_score" : 1.0,
"fields" : {
"aDate" : [ "2015-01-13T20:08:56" ]
}
}, {
"_index" : "myindex",
"_type" : "date-test",
"_id" : "AUrlQnFgk1DYhbTcL2xM",
"_score" : 1.0,
"fields" : {
"aDate" : [ 1421179734000 ]
}
除非使用脚本,否则无法更改日期格式。
curl -XGET http://localhost:9200/myindex/date-test/_search?pretty -d '
{
"query":{
"match_all":{ }
},
"script_fields":{
"aDate":{
"script":"use( groovy.time.TimeCategory ) { new Date( doc[\"aDate\"].value ) }"
}
}
}'
会 return:
{
"_index" : "myindex",
"_type" : "date-test",
"_id" : "AUrlWNTAk1DYhbTcL2xO",
"_score" : 1.0,
"fields" : {
"aDate" : [ "2015-01-13T20:08:56.000Z" ]
}
}, {
"_index" : "myindex",
"_type" : "date-test",
"_id" : "AUrlQnFgk1DYhbTcL2xM",
"_score" : 1.0,
"fields" : {
"aDate" : [ "2015-01-13T20:08:54.000Z" ]
}
}
要应用格式,请按如下方式附加:
"script":"use( groovy.time.TimeCategory ){ new Date( doc[\"aDate\"].value ).format(\"yyyy-MM-dd\") }"
将return"aDate" : [ "2015-01-13" ]
要显示 T
,您需要使用引号,但将其替换为等效的 Unicode:
"script":"use( groovy.time.TimeCategory ){ new Date( doc[\"aDate\"].value ).format(\"yyyy-MM-dd\u0027T\u0027HH:mm:ss\") }"
returns "aDate" : [ "2015-01-13T20:08:54" ]
至 return script_fields 和来源
在您的查询中使用 _source 来指定您想要 return:
的字段
curl -XGET http://localhost:9200/myindex/date-test/_search?pretty -d '
{ "_source" : "name",
"query":{
"match_all":{ }
},
"script_fields":{
"aDate":{
"script":"use( groovy.time.TimeCategory ) { new Date( doc[\"aDate\"].value ) }"
}
}
}'
请问 return 我的 name
字段:
"_source":{"name":"Terry"},
"fields" : {
"aDate" : [ "2015-01-13T20:08:56.000Z" ]
}
使用星号将 return 所有字段,例如:"_source" : "*",
"_source":{"name":"Terry","aDate":1421179736000},
"fields" : {
"aDate" : [ "2015-01-13T20:08:56.000Z" ]
}
编写脚本仅在提取行时才计算答案。这很昂贵,并且使您无法在 Elasticsearch 中使用任何与日期相关的搜索功能。
您应该在插入之前创建一个 elasticsearch "date" 字段。看起来像一个 java Date() 对象 will do.
As mentioned, 答案在 elastic 2.2 中不再有效。我将脚本更改为:
"script":"new Date(doc['time'].value)"
您可以根据this格式化日期。
从 5.0.0 开始,es 使用 Painless
作为脚本语言:link
试试这个(在 6.3.2 中工作)
"script":"doc['aDate'].value.toString('yyyy-MM-dd HH:mm:ss')"
感谢@Archon 的建议。我以您的回答为指导,从 Elasticsearch
的日期时间字段中删除了时间元素
{
"aggs": {
"grp_by_date": {
"terms": {
"size": 200,
"script": "doc['TransactionReconciliationsCreated'].value.toString('yyyy-MM-dd')"
}
}
}
}
如果你使用Elasticsearch 7,想显示指定时区的日期时间,可以这样请求
"query": {
"bool": {
"filter": [
{
"term": {
"client": {
"value": "iOS",
"boost": 1
}
}
}
],
"adjust_pure_negative": true,
"boost": 1
}
},
"script_fields": {
"time": {
"script": "ZonedDateTime input = doc['time'].value; input = input.withZoneSameInstant(ZoneId.of('Asia/Shanghai')); String output = input.format(DateTimeFormatter.ISO_ZONED_DATE_TIME); return output"
}
},
"_source": true,
return
{
...
"_source" : {
...
"time" : 1632903354213
...
},
"fields" : {
"time" : [
"2021-09-29T16:15:54.213+08:00[Asia/Shanghai]"
]
}
},
...
}
我有一个 elasticsearch 索引,其中一个字段 "aDate"(以及许多其他字段)具有以下映射
"aDate" : {
"type" : "date",
"format" : "date_optional_time"
}
当我查询文档时,我得到的结果类似于
"aDate" : 1421179734000,
我知道这是纪元,内部 java/elasticsearch 日期格式,但我想要这样的结果:
"aDate" : "2015-01-13T20:08:54",
我玩脚本
{
"query":{
"match_all":{
}
},
"script_fields":{
"aDate":{
"script":"if (!_source.aDate?.equals('null')) new java.text.SimpleDateFormat('yyyy-MM-dd\'T\'HH:mm:ss').format(new java.util.Date(_source.aDate));"
}
}
}
但它给出了奇怪的结果(脚本基本上可以工作,但 aDate 是唯一返回的字段并且缺少 _source)。这看起来像
"hits": [{
"_index": "idx1",
"_type": "type2",
"_id": "8770",
"_score": 1.0,
"fields": {
"aDate": ["2015-01-12T17:15:47"]
}
},
如果可能的话,我更喜欢没有脚本的解决方案。
当您在 Elasticsearch 中 运行 查询时,您可以请求它 return 原始数据,例如指定 fields:
curl -XGET http://localhost:9200/myindex/date-test/_search?pretty -d '
{
"fields" : "aDate",
"query":{
"match_all":{
}
}
}'
将以您最初存储的格式为您提供日期:
{
"_index" : "myindex",
"_type" : "date-test",
"_id" : "AUrlWNTAk1DYhbTcL2xO",
"_score" : 1.0,
"fields" : {
"aDate" : [ "2015-01-13T20:08:56" ]
}
}, {
"_index" : "myindex",
"_type" : "date-test",
"_id" : "AUrlQnFgk1DYhbTcL2xM",
"_score" : 1.0,
"fields" : {
"aDate" : [ 1421179734000 ]
}
除非使用脚本,否则无法更改日期格式。
curl -XGET http://localhost:9200/myindex/date-test/_search?pretty -d '
{
"query":{
"match_all":{ }
},
"script_fields":{
"aDate":{
"script":"use( groovy.time.TimeCategory ) { new Date( doc[\"aDate\"].value ) }"
}
}
}'
会 return:
{
"_index" : "myindex",
"_type" : "date-test",
"_id" : "AUrlWNTAk1DYhbTcL2xO",
"_score" : 1.0,
"fields" : {
"aDate" : [ "2015-01-13T20:08:56.000Z" ]
}
}, {
"_index" : "myindex",
"_type" : "date-test",
"_id" : "AUrlQnFgk1DYhbTcL2xM",
"_score" : 1.0,
"fields" : {
"aDate" : [ "2015-01-13T20:08:54.000Z" ]
}
}
要应用格式,请按如下方式附加:
"script":"use( groovy.time.TimeCategory ){ new Date( doc[\"aDate\"].value ).format(\"yyyy-MM-dd\") }"
将return"aDate" : [ "2015-01-13" ]
要显示 T
,您需要使用引号,但将其替换为等效的 Unicode:
"script":"use( groovy.time.TimeCategory ){ new Date( doc[\"aDate\"].value ).format(\"yyyy-MM-dd\u0027T\u0027HH:mm:ss\") }"
returns "aDate" : [ "2015-01-13T20:08:54" ]
至 return script_fields 和来源
在您的查询中使用 _source 来指定您想要 return:
的字段curl -XGET http://localhost:9200/myindex/date-test/_search?pretty -d '
{ "_source" : "name",
"query":{
"match_all":{ }
},
"script_fields":{
"aDate":{
"script":"use( groovy.time.TimeCategory ) { new Date( doc[\"aDate\"].value ) }"
}
}
}'
请问 return 我的 name
字段:
"_source":{"name":"Terry"},
"fields" : {
"aDate" : [ "2015-01-13T20:08:56.000Z" ]
}
使用星号将 return 所有字段,例如:"_source" : "*",
"_source":{"name":"Terry","aDate":1421179736000},
"fields" : {
"aDate" : [ "2015-01-13T20:08:56.000Z" ]
}
编写脚本仅在提取行时才计算答案。这很昂贵,并且使您无法在 Elasticsearch 中使用任何与日期相关的搜索功能。
您应该在插入之前创建一个 elasticsearch "date" 字段。看起来像一个 java Date() 对象 will do.
As
"script":"new Date(doc['time'].value)"
您可以根据this格式化日期。
从 5.0.0 开始,es 使用 Painless
作为脚本语言:link
试试这个(在 6.3.2 中工作)
"script":"doc['aDate'].value.toString('yyyy-MM-dd HH:mm:ss')"
感谢@Archon 的建议。我以您的回答为指导,从 Elasticsearch
的日期时间字段中删除了时间元素{
"aggs": {
"grp_by_date": {
"terms": {
"size": 200,
"script": "doc['TransactionReconciliationsCreated'].value.toString('yyyy-MM-dd')"
}
}
}
}
如果你使用Elasticsearch 7,想显示指定时区的日期时间,可以这样请求
"query": {
"bool": {
"filter": [
{
"term": {
"client": {
"value": "iOS",
"boost": 1
}
}
}
],
"adjust_pure_negative": true,
"boost": 1
}
},
"script_fields": {
"time": {
"script": "ZonedDateTime input = doc['time'].value; input = input.withZoneSameInstant(ZoneId.of('Asia/Shanghai')); String output = input.format(DateTimeFormatter.ISO_ZONED_DATE_TIME); return output"
}
},
"_source": true,
return
{
...
"_source" : {
...
"time" : 1632903354213
...
},
"fields" : {
"time" : [
"2021-09-29T16:15:54.213+08:00[Asia/Shanghai]"
]
}
},
...
}