ElasticSearch:在时间戳字段上按小时和分钟过滤数据
ElasticSearch : Filter data by hour and minute on a timestamp field
我用 "TimeStamp" 字段创建了一个索引,该字段具有标准 ISO 格式 "YYYY-MM-DD HH:MM:SS+00:00" 的日期和时间数据。我需要过滤给定日期特定时间之间的数据。例如,我想过滤在 2019 年 1 月份的所有日子的早上 6 点到 12:30 下午之间收集的数据。我使用脚本标签按小时过滤并且它有效。但我无法弄清楚如何在等式中增加分钟数。这是我的查询当前的样子
{
"query": {
"bool": {
"filter": {
"bool": {
"must": [
{
"range": {
"TimeStamp": {
"gte": "2019-01-01T00:00:00.000Z",
"lte": "2019-01-31T23:59:59.000Z"
}
}
},
{
"script": {
"script": {
"source": "(doc['TimeStamp'].value.getHour() >= 6 && doc['TimeStamp'].value.getHour() <= 22)"
}
}
}
]
}
}
}
}
}
这为我提供了特定时间的数据,但我如何向其中添加分钟数?添加 getMinute() 实际上是单独应用它并过滤掉相关结果。有人可以指导我吗?
您走在正确的轨道上 - 正如您所指出的,在所有情况下都应用了 getMinute 方法。但是,使用这种剥离小时和分钟字段的方法,您需要在小时处于上限时添加一组额外的条件only。请注意,如果您还想为下限设置一个可调整的分钟数,则需要额外的条件,但这应该可以帮助您入门:
{
"query": {
"bool": {
"filter": {
"bool": {
"must": [
{
"range": {
"TimeStamp": {
"gte": "2019-01-01T00:00:00.000Z",
"lte": "2019-01-31T23:59:59.000Z"
}
}
},
{
"script": {
"script": {
"params": {
"lowerBoundHour": 6,
"upperBoundHour": 12,
"upperBoundMin": 30
},
"source": """
if (doc['TimeStamp'].value.getHour() >= params.lowerBoundHour && doc['TimeStamp'].value.getHour() <= params.upperBoundHour) {
if (doc['TimeStamp'].value.getHour() == params.upperBoundHour) {
if (doc['TimeStamp'].value.getMinute() <= params.upperBoundMin) {
return true
} else {
return false
}
} else {
return true
}
} else {
return false
}
"""
}
}
}
]
}
}
}
}
}
因为这看起来有点复杂而且可能不是最高效的,我建议您也看看使用 LocalTime
方法转换 TimeStamp
字段,因为它很可能是这样的可以使用更简单的条件从那里写得更干净。
更新:
我觉得这个版本看起来更干净一些:
{
"query": {
"bool": {
"filter": {
"bool": {
"must": [
{
"range": {
"TimeStamp": {
"gte": "2019-01-01T00:00:00.000Z",
"lte": "2019-01-31T23:59:59.000Z"
}
}
},
{
"script": {
"script": {
"params": {
"lowerBoundHour": 6,
"lowerBoundMin": 0,
"upperBoundHour": 12,
"upperBoundMin": 30
},
"source": """
def formattedTime = LocalTime.of(doc['TimeStamp'].value.getHour(), doc['TimeStamp'].value.getMinute());
def lowerBound = LocalTime.of(params.lowerBoundHour, params.lowerBoundMin).minusNanos(1000000);
def upperBound = LocalTime.of(params.upperBoundHour, params.upperBoundMin).plusNanos(1000000);
if (lowerBound.isBefore(formattedTime) && formattedTime.isBefore(upperBound)) {
return true;
} else {
return false;
}
"""
}
}
}
]
}
}
}
}
}
请注意,minusNanos
和 plusNanos
是从您的边界中减去或增加毫秒所必需的 - isBefore
(以及相关的 isAfter
)方法 LocalTime
不包括在内。这也将允许您轻松调整下限时间。
我需要同样的东西(根据时间戳的小时在 Kibana 中过滤),但是 James 的脚本对我不起作用,我需要稍微调整一下(语法是 doc['fieldname'].date.hourOfDay
),所以这是一个对我有用的版本:
{
"query": {
"bool": {
"must": {
"script": {
"script": {
"params": {
"lowerBoundHour": 6,
"upperBoundHour": 20
},
"source": "doc['@timestamp'].date.hourOfDay >= params.lowerBoundHour && doc['@timestamp'].date.hourOfDay <= params.upperBoundHour",
"lang": "painless"
}
}
}
}
}
}
我用 "TimeStamp" 字段创建了一个索引,该字段具有标准 ISO 格式 "YYYY-MM-DD HH:MM:SS+00:00" 的日期和时间数据。我需要过滤给定日期特定时间之间的数据。例如,我想过滤在 2019 年 1 月份的所有日子的早上 6 点到 12:30 下午之间收集的数据。我使用脚本标签按小时过滤并且它有效。但我无法弄清楚如何在等式中增加分钟数。这是我的查询当前的样子
{
"query": {
"bool": {
"filter": {
"bool": {
"must": [
{
"range": {
"TimeStamp": {
"gte": "2019-01-01T00:00:00.000Z",
"lte": "2019-01-31T23:59:59.000Z"
}
}
},
{
"script": {
"script": {
"source": "(doc['TimeStamp'].value.getHour() >= 6 && doc['TimeStamp'].value.getHour() <= 22)"
}
}
}
]
}
}
}
}
}
这为我提供了特定时间的数据,但我如何向其中添加分钟数?添加 getMinute() 实际上是单独应用它并过滤掉相关结果。有人可以指导我吗?
您走在正确的轨道上 - 正如您所指出的,在所有情况下都应用了 getMinute 方法。但是,使用这种剥离小时和分钟字段的方法,您需要在小时处于上限时添加一组额外的条件only。请注意,如果您还想为下限设置一个可调整的分钟数,则需要额外的条件,但这应该可以帮助您入门:
{
"query": {
"bool": {
"filter": {
"bool": {
"must": [
{
"range": {
"TimeStamp": {
"gte": "2019-01-01T00:00:00.000Z",
"lte": "2019-01-31T23:59:59.000Z"
}
}
},
{
"script": {
"script": {
"params": {
"lowerBoundHour": 6,
"upperBoundHour": 12,
"upperBoundMin": 30
},
"source": """
if (doc['TimeStamp'].value.getHour() >= params.lowerBoundHour && doc['TimeStamp'].value.getHour() <= params.upperBoundHour) {
if (doc['TimeStamp'].value.getHour() == params.upperBoundHour) {
if (doc['TimeStamp'].value.getMinute() <= params.upperBoundMin) {
return true
} else {
return false
}
} else {
return true
}
} else {
return false
}
"""
}
}
}
]
}
}
}
}
}
因为这看起来有点复杂而且可能不是最高效的,我建议您也看看使用 LocalTime
方法转换 TimeStamp
字段,因为它很可能是这样的可以使用更简单的条件从那里写得更干净。
更新:
我觉得这个版本看起来更干净一些:
{
"query": {
"bool": {
"filter": {
"bool": {
"must": [
{
"range": {
"TimeStamp": {
"gte": "2019-01-01T00:00:00.000Z",
"lte": "2019-01-31T23:59:59.000Z"
}
}
},
{
"script": {
"script": {
"params": {
"lowerBoundHour": 6,
"lowerBoundMin": 0,
"upperBoundHour": 12,
"upperBoundMin": 30
},
"source": """
def formattedTime = LocalTime.of(doc['TimeStamp'].value.getHour(), doc['TimeStamp'].value.getMinute());
def lowerBound = LocalTime.of(params.lowerBoundHour, params.lowerBoundMin).minusNanos(1000000);
def upperBound = LocalTime.of(params.upperBoundHour, params.upperBoundMin).plusNanos(1000000);
if (lowerBound.isBefore(formattedTime) && formattedTime.isBefore(upperBound)) {
return true;
} else {
return false;
}
"""
}
}
}
]
}
}
}
}
}
请注意,minusNanos
和 plusNanos
是从您的边界中减去或增加毫秒所必需的 - isBefore
(以及相关的 isAfter
)方法 LocalTime
不包括在内。这也将允许您轻松调整下限时间。
我需要同样的东西(根据时间戳的小时在 Kibana 中过滤),但是 James 的脚本对我不起作用,我需要稍微调整一下(语法是 doc['fieldname'].date.hourOfDay
),所以这是一个对我有用的版本:
{
"query": {
"bool": {
"must": {
"script": {
"script": {
"params": {
"lowerBoundHour": 6,
"upperBoundHour": 20
},
"source": "doc['@timestamp'].date.hourOfDay >= params.lowerBoundHour && doc['@timestamp'].date.hourOfDay <= params.upperBoundHour",
"lang": "painless"
}
}
}
}
}
}