首页 > 解决方案 > 使用 Elasticsearch 检索给定日期不在两个 Date 类型字段之间的文档

问题描述

我在 Elasticsearch 7.10.1 中有一个具有以下映射的文档:

{
  "mappings": {
     "properties": {
       "id": { "type": "text"},
       "nonAvailabilities": {
         "type": "nested",
         "properties": {
            "startDate": { "type": "date" },
            "endDate": { "type": "date" }
          }
       }
     }
  }
}

我想检索作为参数传递的日期不在 and 之间的所有nonAvailabilities.startDate文档nonAvailabilities.endDate

我尝试了以下查询,但它返回不需要的文档:

{
  "query":{
    "bool":{
       "filter":[
          {
             "bool":{
                "must_not":[
                   {
                      "nested":{
                           "path":"nonAvailabilities",
                           "query":{
                             "bool":{
                               "must":[
                                  {
                                     "range":{
                                        "startDate":{
                                           "lte":"2021-08-19T10:30",
                                           "format": "yyyy-MM-dd HH:mm"
                                        }  
                                     }  
                                  },
                                  {
                                     "range":{
                                        "endDate":{
                                            "gte":"2021-08-19T10:30",
                                            "format": "yyyy-MM-dd HH:mm"
                                        }
                                     }
                                  }
                               ]
                            }
                         }
                      }
                   }
                ]
             }
          }
       ]
    }
 }
}

我还使用 Spring Data 实现了这个查询,但它也返回了不需要的文档:

BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
queryBuilder.filter(
      QueryBuilders.boolQuery()
          .mustNot(
              QueryBuilders.nestedQuery("nonAvailabilities",
                  QueryBuilders
                      .boolQuery()
                     .must(QueryBuilders.rangeQuery("startDate").lte(criteria.getWhen()))
                      .must(QueryBuilders.rangeQuery("endDate").gte(criteria.getWhen())),
                  ScoreMode.None)));
 ...
 Query searchQuery = new NativeSearchQueryBuilder()
    .withQuery(queryBuilder).build();

 reactiveElasticsearchOperations
    .searchForPage(searchQuery, MyDocument.class, IndexCoordinates.of("myDocuments"));
 ...

你知道我的查询有什么问题吗?

标签: jsonjava-8spring-data-elasticsearchelasticsearch-7

解决方案


您的查询是正确的。

您需要在 startDate 和 endDate 前加上“nonAvailabilities”。嵌套查询中的字段应该是完全限定的,因此 startDate 将是 nonAvailabilities.startDate

{
  "query":{
    "bool":{
       "filter":[
          {
             "bool":{
                "must_not":[
                   {
                      "nested":{
                           "path":"nonAvailabilities",
                           "query":{
                             "bool":{
                               "must":[
                                  {
                                     "range":{
                                        "nonAvailabilities.startDate":{
                                           "lte":"2021-08-19T10:30",
                                           "format": "yyyy-MM-dd HH:mm"
                                        }  
                                     }  
                                  },
                                  {
                                     "range":{
                                        "nonAvailabilities.endDate":{
                                            "gte":"2021-08-19T10:30",
                                            "format": "yyyy-MM-dd HH:mm"
                                        }
                                     }
                                  }
                               ]
                            }
                         }
                      }
                   }
                ]
             }
          }
       ]
    }
 }
}

推荐阅读