Elasticsearch筛选完整日期数据,排除仅年份格式的记录
嘿,我来帮你解决这个Elasticsearch的日期过滤问题!
为什么你原来的查询没生效?
你之前在range里加的format参数,其实是用来告诉ES怎么解析你输入的查询条件(比如gte/lt的日期值),而不是用来筛选字段本身的格式,所以它没法帮你排除纯年份的记录。
靠谱的解决方案来了
要排除premiere_date是纯yyyy格式的记录,我们可以用bool查询的must_not子句,搭配以下几种方法:
方法1:用脚本判断字符串长度(简单直接)
纯年份的字符串长度是4位,而yyyy-MM是7位、yyyy-MM-dd是10位,直接判断长度就能过滤:
{ "query": { "bool": { "filter": [ { "range": { "premiere_date": { "gte": "1983-12-22", "lt": "1988-03-21" } } } ], "must_not": [ { "script": { "script": { "source": "doc['premiere_date'].value.length() == 4", "lang": "painless" } } } ] } } }
方法2:用正则表达式匹配格式
用正则匹配必须包含横杠的日期字符串,这样就自动排除纯年份的记录:
{ "query": { "bool": { "filter": [ { "range": { "premiere_date": { "gte": "1983-12-22", "lt": "1988-03-21" } } }, { "regexp": { "premiere_date": "^\\d{4}-.*" } } ] } } }
这个正则的意思是:开头是4位数字,后面跟着横杠,再跟任意内容——正好匹配yyyy-MM和yyyy-MM-dd格式。
方法3:利用日期类型的内置属性(推荐)
因为你的premiere_date是date类型,ES会把纯年份1985自动解析成1985-01-01。如果纯年份的记录都是默认的1月1日,那我们可以通过判断月份和日期来排除:
{ "query": { "bool": { "filter": [ { "range": { "premiere_date": { "gte": "1983-12-22", "lt": "1988-03-21" } } } ], "must_not": [ { "bool": { "must": [ { "term": { "premiere_date.month": 1 } }, { "term": { "premiere_date.day": 1 } } ] } } ] } } }
注意:这个方法需要确保你的date字段已经开启了fielddata,或者用了runtime字段来访问month和day属性哦。
测试效果
用你给的示例数据跑上面任意一个查询,都会返回name为a和b的两条记录,完美排除c的纯年份记录,符合你的需求!
内容的提问来源于stack exchange,提问作者bato3
相关产品推荐
相关产品推荐

