Elasticsearch 查询带有日期的对象数组

Elasticsearch query on array of objects with date

您好,我是 Elasticsearch 的新手,正在尝试使用 spring-data-elasticsearch 实施解决方案。我的索引数据如下所示:

[
  {
    "worker": "A",
    "availability": [
      {
        "startDate": "2020-01-12",
        "endDate": "2020-02-12"
      },
      {
        "startDate": "2020-04-12",
        "endDate": "2020-05-12"
      }
    ]
  },
  {
    "worker": "B",
    "availability": [
      {
        "startDate": "2020-04-12",
        "endDate": "2020-11-12"
      }
    ]
  }
]

通过参考弹性文档,我计划使用范围查询来获取指定日期范围内的记录,例如,我想获取“2020-05-12 到 2020-06-12”之间的可用工作人员.这是我形成的查询:

{
    "query": {
        "bool": {
            "must": [
                {
                    "nested": {
                        "query": {
                            "range": {
                                "availability.start_date": {
                                    "from": "2020-05-12T00:00:00.000Z",
                                    "to": "2020-06-12T00:00:00.000Z",
                                    "include_lower": true,
                                    "include_upper": true,
                                    "boost": 1.0
                                }
                            }
                        },
                        "path": "availability",
                        "ignore_unmapped": false,
                        "score_mode": "none",
                        "boost": 1.0
                    }
                }
            ],
            "adjust_pure_negative": true,
            "boost": 1.0
        }
    }
}

上面的查询在执行时显示空命中,但是当我使用索引的日期时,我能够获取记录(例如,如果我将日期指定为“2020-04-12 到 2020-11 -12”显示工人 B 结果)。根据范围查询,如果我没记错的话,它也应该适用于我之前的案例。我遵循的方法有什么问题吗?请指教

您没有 start_date (!!) 介于 2020-05-122020-06-12 之间的工人。我认为您需要采取不同的方式来实现您想要实现的目标。

由于您尝试匹配范围,因此利用 date_range field type 可能会更容易。您的映射应如下所示:

PUT your-index
{
  "mappings": {
    "properties": {
      "availability": {
        "type": "date_range", 
        "format": "yyyy-MM-dd"
      }
    }
  }
}

然后您可以像这样索引所有工作人员的可用性:

{
  "worker": "A",
  "availability": [
    {
      "gte": "2020-01-12",
      "lte": "2020-02-12"
    },
    {
      "gte": "2020-04-12",
      "lte": "2020-05-12"
    }
  ]
}
{
  "worker": "B",
  "availability": [
    {
      "gte": "2020-04-12",
      "lte": "2020-11-12"
    }
  ]
}

然后您可以像这样执行您想要的搜索:

{
  "query": {
    "range": {
      "availability": {
        "gte": "2020-05-12",
        "lte": "2020-06-12",
        "relation": "contains"
      }
    }
  }
}

你会发现只有工人 B 满足条件。

更新

您在 Java 中的查询需要像这样:

    final BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();

    queryBuilder.must(QueryBuilders.matchQuery("name", "A"));

    RangeQueryBuilder availability = QueryBuilders.rangeQuery("availability")
           .gte(query.getStartDate())
           .lte(query.getEndDate());

    queryBuilder.must(availability);

    Pageable pageable = PageRequest.of(pageNumber, pageSize);

    // @formatter:off
    return new NativeSearchQueryBuilder()
            .withPageable(pageable)
            .withQuery(queryBuilder)
            .build();