如何根据已保存搜索中的日期字段显示到期、逾期和未到期
How to display Due, Over Due and Not Due based on a date field in Saved Search
例如,我在索引中有一个日期字段 delivery_datetime
,我必须向用户显示当天的特定包裹是今天到期还是过期或未到期
我无法创建一个单独的字段并重新编制索引,因为它基于当前日期并且每天都在变化,例如,如果我必须在编制索引时进行计算,我必须每天重新编制索引,这是不可行的,因为我有很多数据。
我可能会使用查询更新,但我的索引经常通过 Python 脚本更新,以为我们没有 ACID 属性 这里我们会有版本冲突。
据我所知,我认为我唯一的选择是使用脚本字段。
如果我必须用伪代码编写逻辑:
Due - delivery_datetime.dateOnly == now.dateOnly
Over Due - delivery_datetime.dateOnly < now.dateOnly
Not Due - delivery_datetime.dateOnly > now.dateOnly
如果我生成 CSV,我认为我有很多数据我不希望脚本字段对集群性能产生重大影响。
所以我需要一些帮助才能在脚本领域有效地做到这一点,或者如果有任何完全不同的解决方案也会有很大帮助。
如果脚本字段是唯一的解决方案,希望通过提供无痛脚本来获得帮助。
一旦我们排除了 doc upserts/updates,基本上有两种方法:script_fields
或 filter aggregations
。
我们首先假设您的映射类似于:
{
"mappings": {
"properties": {
"delivery_datetime": {
"type": "object",
"properties": {
"dateOnly": {
"type": "date",
"format": "dd.MM.yyyy"
}
}
}
}
}
}
现在,如果我们通过其 ID 来过滤所有包,并想知道它在哪个 due-state 中,我们可以像这样创建 3 个脚本字段:
GET parcels/_search
{
"_source": "timeframe_*",
"script_fields": {
"timeframe_due": {
"script": {
"source": "doc['delivery_datetime.dateOnly'].value.dayOfMonth == params.nowDayOfMonth",
"params": {
"nowDayOfMonth": 8
}
}
},
"timeframe_overdue": {
"script": {
"source": "doc['delivery_datetime.dateOnly'].value.dayOfMonth < params.nowDayOfMonth",
"params": {
"nowDayOfMonth": 8
}
}
},
"timeframe_not_due": {
"script": {
"source": "doc['delivery_datetime.dateOnly'].value.dayOfMonth > params.nowDayOfMonth",
"params": {
"nowDayOfMonth": 8
}
}
}
}
}
这将 return 类似于:
...
"fields" : {
"timeframe_due" : [
true
],
"timeframe_not_due" : [
false
],
"timeframe_overdue" : [
false
]
}
这是微不足道的,日期数学有一个重要的弱点,将在下面解决。
或者,我们可以使用 3 个过滤器聚合并类似地仅过滤出 1 个有问题的文档,如下所示:
GET parcels/_search
{
"size": 0,
"query": {
"ids": {
"values": [
"my_id_thats_due_today"
]
}
},
"aggs": {
"due": {
"filter": {
"range": {
"delivery_datetime.dateOnly": {
"gte": "now/d",
"lte": "now/d"
}
}
}
},
"overdue": {
"filter": {
"range": {
"delivery_datetime.dateOnly": {
"lt": "now/d"
}
}
}
},
"not_due": {
"filter": {
"range": {
"delivery_datetime.dateOnly": {
"gt": "now/d"
}
}
}
}
}
}
屈服
...
"aggregations" : {
"overdue" : {
"doc_count" : 0
},
"due" : {
"doc_count" : 1
},
"not_due" : {
"doc_count" : 0
}
}
现在第二种方法的优点如下:
不涉及脚本 -> 执行速度更快。
更重要的是,您不必担心 day-of-month 数学运算,例如 12 月 15 日晚于 11 月 20 日,但琐碎的 day-of-month 比较会产生其他结果。您可以在脚本中实现类似的东西,但越复杂,执行速度越差。
您可以放弃 ID 过滤并在内部仪表板中使用这些聚合计数。甚至可能是客户仪表板,但普通客户很少有大量包裹可以合理聚合。
回答我自己的问题,这是对我有用的。
脚本字段脚本:
def DiffMillis = 0;
if(!doc['delivery_datetime'].empty) {
// Converting each to days, 1000*60*60*24 = 86400000
DiffMillis = (new Date().getTime() / 86400000) - (doc['delivery_datetime'].value.getMillis() / 86400000);
}
doc['delivery_datetime'].empty ? "No Due Date": (DiffMillis==0?"Due": (DiffMillis>0?"Over Due":"Not Due") )
我特地用了三元运算符,因为如果我用if else
那么我就得用return
,如果我用return
我在为脚本字段添加过滤器时遇到 search_phase_execution_exception
。
例如,我在索引中有一个日期字段 delivery_datetime
,我必须向用户显示当天的特定包裹是今天到期还是过期或未到期
我无法创建一个单独的字段并重新编制索引,因为它基于当前日期并且每天都在变化,例如,如果我必须在编制索引时进行计算,我必须每天重新编制索引,这是不可行的,因为我有很多数据。
我可能会使用查询更新,但我的索引经常通过 Python 脚本更新,以为我们没有 ACID 属性 这里我们会有版本冲突。
据我所知,我认为我唯一的选择是使用脚本字段。
如果我必须用伪代码编写逻辑:
Due - delivery_datetime.dateOnly == now.dateOnly
Over Due - delivery_datetime.dateOnly < now.dateOnly
Not Due - delivery_datetime.dateOnly > now.dateOnly
如果我生成 CSV,我认为我有很多数据我不希望脚本字段对集群性能产生重大影响。
所以我需要一些帮助才能在脚本领域有效地做到这一点,或者如果有任何完全不同的解决方案也会有很大帮助。
如果脚本字段是唯一的解决方案,希望通过提供无痛脚本来获得帮助。
一旦我们排除了 doc upserts/updates,基本上有两种方法:script_fields
或 filter aggregations
。
我们首先假设您的映射类似于:
{
"mappings": {
"properties": {
"delivery_datetime": {
"type": "object",
"properties": {
"dateOnly": {
"type": "date",
"format": "dd.MM.yyyy"
}
}
}
}
}
}
现在,如果我们通过其 ID 来过滤所有包,并想知道它在哪个 due-state 中,我们可以像这样创建 3 个脚本字段:
GET parcels/_search
{
"_source": "timeframe_*",
"script_fields": {
"timeframe_due": {
"script": {
"source": "doc['delivery_datetime.dateOnly'].value.dayOfMonth == params.nowDayOfMonth",
"params": {
"nowDayOfMonth": 8
}
}
},
"timeframe_overdue": {
"script": {
"source": "doc['delivery_datetime.dateOnly'].value.dayOfMonth < params.nowDayOfMonth",
"params": {
"nowDayOfMonth": 8
}
}
},
"timeframe_not_due": {
"script": {
"source": "doc['delivery_datetime.dateOnly'].value.dayOfMonth > params.nowDayOfMonth",
"params": {
"nowDayOfMonth": 8
}
}
}
}
}
这将 return 类似于:
...
"fields" : {
"timeframe_due" : [
true
],
"timeframe_not_due" : [
false
],
"timeframe_overdue" : [
false
]
}
这是微不足道的,日期数学有一个重要的弱点,将在下面解决。
或者,我们可以使用 3 个过滤器聚合并类似地仅过滤出 1 个有问题的文档,如下所示:
GET parcels/_search
{
"size": 0,
"query": {
"ids": {
"values": [
"my_id_thats_due_today"
]
}
},
"aggs": {
"due": {
"filter": {
"range": {
"delivery_datetime.dateOnly": {
"gte": "now/d",
"lte": "now/d"
}
}
}
},
"overdue": {
"filter": {
"range": {
"delivery_datetime.dateOnly": {
"lt": "now/d"
}
}
}
},
"not_due": {
"filter": {
"range": {
"delivery_datetime.dateOnly": {
"gt": "now/d"
}
}
}
}
}
}
屈服
...
"aggregations" : {
"overdue" : {
"doc_count" : 0
},
"due" : {
"doc_count" : 1
},
"not_due" : {
"doc_count" : 0
}
}
现在第二种方法的优点如下:
不涉及脚本 -> 执行速度更快。
更重要的是,您不必担心 day-of-month 数学运算,例如 12 月 15 日晚于 11 月 20 日,但琐碎的 day-of-month 比较会产生其他结果。您可以在脚本中实现类似的东西,但越复杂,执行速度越差。
您可以放弃 ID 过滤并在内部仪表板中使用这些聚合计数。甚至可能是客户仪表板,但普通客户很少有大量包裹可以合理聚合。
回答我自己的问题,这是对我有用的。
脚本字段脚本:
def DiffMillis = 0;
if(!doc['delivery_datetime'].empty) {
// Converting each to days, 1000*60*60*24 = 86400000
DiffMillis = (new Date().getTime() / 86400000) - (doc['delivery_datetime'].value.getMillis() / 86400000);
}
doc['delivery_datetime'].empty ? "No Due Date": (DiffMillis==0?"Due": (DiffMillis>0?"Over Due":"Not Due") )
我特地用了三元运算符,因为如果我用if else
那么我就得用return
,如果我用return
我在为脚本字段添加过滤器时遇到 search_phase_execution_exception
。