Elasticsearch嵌套字段range查询:筛选所有时间范围过期的文档
Elasticsearch 筛选所有nested元素时间范围均不包含指定日期的文档
问题场景
索引中存在nested类型字段plazos,每个元素包含fechainicio(开始日期)、fechafin(结束日期)等属性。已实现匹配至少一个plazos元素时间范围包含指定日期的文档,但需要筛选所有plazos元素时间范围均不包含指定日期的文档。直接用must_not改写原range查询无法满足需求——因为只要有一个元素不包含指定日期,文档就会被匹配,而非所有元素都不包含。
示例plazos数据
"plazos" : [ { "id" : 1, "fechainicio" : "01/04/2023", "fechafin" : "31/04/2023" }, { "id" : 2, "fechainicio" : "09/11/2023", "fechafin" : "29/11/2023" } ]
原匹配“包含指定日期”的查询
"bool" : { "must" : [ { "range" : { "plazos.fechainicio" : { "from" : null, "to" : "19/04/2023", "include_lower" : true, "include_upper" : true, "boost" : 1.0 } } }, { "range" : { "plazos.fechafin" : { "from" : "19/04/2023", "to" : null, "include_lower" : true, "include_upper" : true, "boost" : 1.0 } } } ], "adjust_pure_negative" : true, "boost" : 1.0 }
plazos字段映射
"plazos" : { "type" : "nested", "properties" : { "fechafin" : { "type" : "date", "format" : "dd/MM/yyyy" }, "fechainicio" : { "type" : "date", "format" : "dd/MM/yyyy" }, "id" : { "type" : "integer", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "masinformacion" : { "type" : "keyword", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } } } }
解决方案
核心是使用nested查询配合外层bool.must_not,精准检查每个嵌套元素:
{ "bool": { "must_not": [ { "nested": { "path": "plazos", "query": { "bool": { "must": [ { "range": { "plazos.fechainicio": { "lte": "19/04/2023", "format": "dd/MM/yyyy" } } }, { "range": { "plazos.fechafin": { "gte": "19/04/2023", "format": "dd/MM/yyyy" } } } ] } } } } ] } }
逻辑说明
- 外层
bool.must_not:排除所有满足内部条件的文档 nested查询:指定path: "plazos",确保查询作用于每个独立的plazos嵌套元素,而非扁平处理整个数组- 嵌套内的查询逻辑:复用原有的“检查plazos元素包含指定日期”的条件——只要有任何一个plazos元素满足该条件,整个文档就会被排除
- 最终效果:返回的文档中,所有plazos元素的时间范围都不包含指定日期
内容的提问来源于stack exchange,提问作者Miguel Abreu
相关产品推荐
相关产品推荐

