Elasticsearch:含Script的Query Filter不生效问题排查
问题:Elasticsearch脚本查询过滤周一数据后聚合结果不符合预期
我需要筛选出record_created_at字段为周一的数据,编写了如下Script查询:
{ "_source": "false", "query": { "bool": { "must": [ { "script": { "script": "doc['record_created_at'].value.getDayOfWeek() == 1" } } ] } }, "aggs": { "record_created_at_agg": { "date_histogram": { "field": "record_created_at", "calendar_interval": "day", "format": "yyyy-MM-dd" } } }, "fields": [ "record_created_at" ], "size": 10000 }
但返回的聚合结果未应用该过滤条件,仍包含非周一的日期桶。而当我使用match查询指定具体时间时:
{ "_source": "false", "query": { "bool": { "must": [ { "match": { "record_created_at": "2023-05-08T16:14:58.000Z" } } ] } }, "aggs": { "filtered_dates": { "date_histogram": { "field": "record_created_at", "calendar_interval": "day", "format": "yyyy-MM-dd" } } }, "fields": [ "record_created_at" ], "size": 10000 }
聚合结果符合预期。请问我的Script查询哪里出错了?
问题原因及解决方案
一、脚本过滤条件逻辑错误
在Elasticsearch的Painless脚本中,doc['record_created_at'].value.getDayOfWeek()返回的是java.time.DayOfWeek枚举对象,而非数字。你直接用==1做比较,这个判断永远不成立(枚举类型和数字无法直接相等),导致脚本过滤完全失效,所有文档都被保留,聚合自然会包含所有日期的桶。
正确的写法有两种:
- 使用枚举常量判断:
"script": "doc['record_created_at'].value.getDayOfWeek() == DayOfWeek.MONDAY" - 获取枚举对应的ISO标准数字(周一为1,周日为7):
"script": "doc['record_created_at'].value.getDayOfWeek().getValue() == 1"
二、聚合默认返回空桶导致误解
即使脚本过滤生效,默认的date_histogram聚合会返回所有符合时间范围的桶——哪怕桶内没有匹配的文档(doc_count: 0)。如果你只想看到有数据的周一桶,需要在聚合中添加min_doc_count: 1参数,过滤掉空桶。
修正后的完整查询
{ "_source": "false", "query": { "bool": { "must": [ { "script": { "script": "doc['record_created_at'].value.getDayOfWeek().getValue() == 1" } } ] } }, "aggs": { "record_created_at_agg": { "date_histogram": { "field": "record_created_at", "calendar_interval": "day", "format": "yyyy-MM-dd", "min_doc_count": 1 } } }, "fields": [ "record_created_at" ], "size": 10000 }
内容的提问来源于stack exchange,提问作者DilLip_Chowdary
相关产品推荐
相关产品推荐

