两个日期字段之间计算的平均差异
Average of differences calculated between two date fields
我正在开发一个项目,该项目使用 Elasticsearch
来存储数据并显示一些复杂的统计数据。
我有一个 index 看起来像这样:
Reservation {
id: number
check_in: Date
check_out: Date
created_at: Date
// other fields...
}
我需要计算check_in
和created_at
[=38=之间的平均天数差] of my Reservation
s 在特定日期范围内并将结果显示为数字。
我试过了 query
:
{
"script_fields": {
"avgDates": {
"script": {
"lang": "expression",
"source": "doc['created_at'].value - doc['check_in'].value"
}
}
},
"query": {
"bool": {
"must": [
{
"range": {
"created_at": {
"gte": "{{lastMountTimestamp}}",
"lte": "{{currentTimestamp}}"
}
}
}
]
}
},
"size": 0,
"aggs": {
"avgBetweenDates": {
"avg": {
"field": "avgDates"
}
}
}
}
日期字段 以 ISO 8601 格式保存(例如:2020-03-11T14:25:15+00:00) ,我不知道这是否会产生问题。
它捕获了一些命中,因此,查询肯定有效!但是,它总是 returns null
作为 avgBetweenDates
聚合的值。
我需要这样的结果:
"aggregations": {
"avgBetweenDates": {
"value": 3.14159 // Π is just an example!
}
}
任何想法都会有所帮助!
谢谢。
在 _search
上下文中创建的脚本字段可以 only be consumed within that scope。它们在 aggregations
内不可见!这意味着您必须选择
- 将您的脚本移动到
aggs
部分和
- 一个scripted metric聚合(相当慢且难以正确)
- 或在索引时创建一个
dateDifference
字段(最好是 int
-- 时间戳的差异),这将使您能够执行强大的数字聚合,如 extended stats 提供统计上有用的输出,例如:
{
...
"aggregations": {
"grades_stats": {
"count": 2,
"min": 50.0,
"max": 100.0,
"avg": 75.0,
"sum": 150.0,
"sum_of_squares": 12500.0,
"variance": 625.0,
"std_deviation": 25.0,
"std_deviation_bounds": {
"upper": 125.0,
"lower": 25.0
}
}
}
}
并且总是比使用脚本计算时间戳差异更快。
脚本字段不是 ES 中的存储字段。您只能对存储的字段执行聚合,因为 scripted fields
是动态创建的。
您可以简单地移动 Average Aggregation 中的脚本逻辑,如下所示。请注意,为了便于理解,我创建了示例映射、文档、查询及其响应。
映射:
PUT my_date_index
{
"mappings": {
"properties": {
"check_in":{
"type":"date",
"format": "date_time"
},
"check_out":{
"type": "date",
"format": "date_time"
},
"created_at":{
"type": "date",
"format": "date_time"
}
}
}
}
示例文档:
POST my_date_index/_doc/1
{
"check_in": "2019-01-15T00:00:00.000Z",
"check_out": "2019-01-20T00:00:00.000Z",
"created_at": "2019-01-17T00:00:00.000Z"
}
POST my_date_index/_doc/2
{
"check_in": "2019-01-15T00:00:00.000Z",
"check_out": "2019-01-22T00:00:00.000Z",
"created_at": "2019-01-20T00:00:00.000Z"
}
聚合查询:
POST my_date_index/_search
{
"size": 0,
"aggs": {
"my_dates_diff": {
"avg": {
"script": """
ZonedDateTime d1 = doc['created_at'].value;
ZonedDateTime d2 = doc['check_in'].value;
long differenceInMillis = ChronoUnit.MILLIS.between(d1, d2);
return Math.abs(differenceInMillis/86400000);
"""
}
}
}
}
注意,您想要天数的差异。上面的逻辑就是这样做的。
回复:
{
"took" : 2,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"my_dates_diff" : {
"value" : 3.5 <---- Average in Number of Days
}
}
}
希望对您有所帮助!
我正在开发一个项目,该项目使用 Elasticsearch
来存储数据并显示一些复杂的统计数据。
我有一个 index 看起来像这样:
Reservation {
id: number
check_in: Date
check_out: Date
created_at: Date
// other fields...
}
我需要计算check_in
和created_at
[=38=之间的平均天数差] of my Reservation
s 在特定日期范围内并将结果显示为数字。
我试过了 query
:
{
"script_fields": {
"avgDates": {
"script": {
"lang": "expression",
"source": "doc['created_at'].value - doc['check_in'].value"
}
}
},
"query": {
"bool": {
"must": [
{
"range": {
"created_at": {
"gte": "{{lastMountTimestamp}}",
"lte": "{{currentTimestamp}}"
}
}
}
]
}
},
"size": 0,
"aggs": {
"avgBetweenDates": {
"avg": {
"field": "avgDates"
}
}
}
}
日期字段 以 ISO 8601 格式保存(例如:2020-03-11T14:25:15+00:00) ,我不知道这是否会产生问题。
它捕获了一些命中,因此,查询肯定有效!但是,它总是 returns null
作为 avgBetweenDates
聚合的值。
我需要这样的结果:
"aggregations": {
"avgBetweenDates": {
"value": 3.14159 // Π is just an example!
}
}
任何想法都会有所帮助!
谢谢。
在 _search
上下文中创建的脚本字段可以 only be consumed within that scope。它们在 aggregations
内不可见!这意味着您必须选择
- 将您的脚本移动到
aggs
部分和 - 一个scripted metric聚合(相当慢且难以正确)
- 或在索引时创建一个
dateDifference
字段(最好是int
-- 时间戳的差异),这将使您能够执行强大的数字聚合,如 extended stats 提供统计上有用的输出,例如:
{
...
"aggregations": {
"grades_stats": {
"count": 2,
"min": 50.0,
"max": 100.0,
"avg": 75.0,
"sum": 150.0,
"sum_of_squares": 12500.0,
"variance": 625.0,
"std_deviation": 25.0,
"std_deviation_bounds": {
"upper": 125.0,
"lower": 25.0
}
}
}
}
并且总是比使用脚本计算时间戳差异更快。
脚本字段不是 ES 中的存储字段。您只能对存储的字段执行聚合,因为 scripted fields
是动态创建的。
您可以简单地移动 Average Aggregation 中的脚本逻辑,如下所示。请注意,为了便于理解,我创建了示例映射、文档、查询及其响应。
映射:
PUT my_date_index
{
"mappings": {
"properties": {
"check_in":{
"type":"date",
"format": "date_time"
},
"check_out":{
"type": "date",
"format": "date_time"
},
"created_at":{
"type": "date",
"format": "date_time"
}
}
}
}
示例文档:
POST my_date_index/_doc/1
{
"check_in": "2019-01-15T00:00:00.000Z",
"check_out": "2019-01-20T00:00:00.000Z",
"created_at": "2019-01-17T00:00:00.000Z"
}
POST my_date_index/_doc/2
{
"check_in": "2019-01-15T00:00:00.000Z",
"check_out": "2019-01-22T00:00:00.000Z",
"created_at": "2019-01-20T00:00:00.000Z"
}
聚合查询:
POST my_date_index/_search
{
"size": 0,
"aggs": {
"my_dates_diff": {
"avg": {
"script": """
ZonedDateTime d1 = doc['created_at'].value;
ZonedDateTime d2 = doc['check_in'].value;
long differenceInMillis = ChronoUnit.MILLIS.between(d1, d2);
return Math.abs(differenceInMillis/86400000);
"""
}
}
}
}
注意,您想要天数的差异。上面的逻辑就是这样做的。
回复:
{
"took" : 2,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"my_dates_diff" : {
"value" : 3.5 <---- Average in Number of Days
}
}
}
希望对您有所帮助!