Elasticsearch range查询返回空响应问题排查方案
问题根因
查询返回空结果是两个配置问题导致的:
- 写入数据前没有预先定义
Date字段的映射类型,Elasticsearch默认动态映射规则不会自动识别MM/dd/yyyy HH:mm:ss.SSS格式的字符串为日期类型,会把该字段存为text+keyword类型的普通字符串,不会做日期维度的逻辑解析。 - 对字符串字段执行range查询时,比较逻辑走的是字符字典序,而你用的
月/日/年格式字符串的字典序和实际时间先后顺序完全不匹配,自然无法筛选出符合时间范围的结果。
修复步骤
测试环境下直接按以下流程操作即可:
- 删除映射配置错误的存量索引
DELETE favorite
- 创建新索引,提前定义
Date字段为date类型,并指定和你的写入数据匹配的日期解析格式
PUT favorite { "mappings": { "properties": { "first_name": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, "Date": { "type": "date", "format": "MM/dd/yyyy HH:mm:ss.SSS||strict_date_optional_time||epoch_millis" } } } }
- 重新执行原来的三条写入语句,导入测试数据
PUT favorite/_doc/1 { "first_name": "Lisa", "Date": "07/12/2022 16:04:30.496" } PUT favorite/_doc/2 { "first_name": "Ann", "Date": "07/12/2022 17:04:30.496" } PUT favorite/_doc/3 { "first_name": "Ming", "Date": "07/12/2022 18:04:30.496" }
- 再次执行原来的range查询,就能正常返回时间区间内的Lisa、Ann两条文档。
GET favorite/_search { "query": { "range": { "Date": { "gte": "07/12/2022 16:04:30.496", "lte": "07/12/2022 17:05:30.496" } } } }
生产环境不允许直接删除索引的场景,可以新建一个映射配置正确的索引,通过
reindex接口将旧索引数据迁移到新索引,再通过索引别名无感知切换即可,不需要调整业务侧的读写逻辑。日常使用中如果没有特殊格式要求,写入时间时优先使用ISO8601标准格式(如2022-07-12T16:04:30.496Z),不需要额外配置日期格式就能被Elasticsearch自动识别为date类型,减少配置错误。
内容的提问来源于stack exchange,提问作者misterkevin
相关产品推荐
相关产品推荐

