ElasticSearch-查找所有嵌套文档不与日期范围相交的文档

时间:2019-02-15 18:00:38

标签: elasticsearch

我有一个名为employees的索引,其中包含一个嵌套的日期时间范围集合,称为shifts。我需要找到在特定输入日期时间范围内可用的所有用户(即输入日期范围不与任何班次相交)。如何使用ElasticSearch做到这一点?这就是我的索引的样子(为简洁起见,对其进行了整理),不确定是否正确:

{
    "mappings": {
        "employee": {
            "properties": {
                "email": {
                    "type": "text",
                    "fields": {
                        "raw": {
                            "type": "keyword"
                        }
                    }
                },
                "shifts": {
                    "type": "nested",
                    "properties": {
                        "shift": {
                            "type": "date_range"
                        }
                    }
                }
            }
        }
    }
}

1 个答案:

答案 0 :(得分:2)

只要您拥有nested数据类型,就需要使用nested query

请注意,我在映射中为yyyy-MM-dd使用了简单的shifts.shift格式,如下所示。我还提供了示例文档,查询和响应。

请注意我提到的两个方案/查询,以便您清楚最适合您的用例的情况。

映射

PUT someindex
{
    "mappings": {
        "employee": {
            "properties": {
                "email": {
                    "type": "text",
                    "fields": {
                        "raw": {
                            "type": "keyword"
                        }
                    }
                },
                "shifts": {
                    "type": "nested",
                    "properties": {
                        "shift": {
                            "type": "date_range",
                            "format": "yyyy-MM-dd"
                        }
                    }
                }
            }
        }
    }
}

样本文档:

POST someindex/employee/1
{
  "email": "john@abc.com",
  "shifts": [
    {
      "shift": {
        "gte": "2019-01-01",
        "lte": "2019-01-03"
      }
    }
  ]
}

POST someindex/employee/2
{
  "email": "jane@abc.com",
  "shifts": [
    {
      "shift": {
        "gte": "2019-01-04",
        "lte": "2019-01-07"
      }
    }
  ]
}

POST someindex/employee/3
{
  "email": "jack@abc.com",
  "shifts": [
    {
      "shift": {
        "gte": "2019-01-08",
        "lte": "2019-01-10"
      }
    }
  ]
}

查询

场景1:在特定范围内可用的用户列表,例如从2019-01-012019-01-04。还要注意在下面的查询中使用nested关键字

POST someindex/_search
{  
   "query":{  
      "bool":{  
         "must":[  
            {  
               "nested":{  
                  "path":"shifts",
                  "query":{  
                     "range":{  
                        "shifts.shift":{  
                           "gte":"2019-01-01",
                           "lte":"2019-01-04",
                        }
                     }
                  }
               }
            }
         ]
      }
   }
}

响应

查看示例文档,您可以看到结果返回了JohnJane。请注意,您会同时获得这两者,因为默认情况下,范围为intersection

{
  "took" : 3,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 2,
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "someindex",
        "_type" : "employee",
        "_id" : "2",
        "_score" : 1.0,
        "_source" : {
          "email" : "jane@abc.com",
          "shifts" : [
            {
              "shift" : {
                "gte" : "2019-01-04",
                "lte" : "2019-01-07"
              }
            }
          ]
        }
      },
      {
        "_index" : "someindex",
        "_type" : "employee",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "email" : "john@abc.com",
          "shifts" : [
            {
              "shift" : {
                "gte" : "2019-01-01",
                "lte" : "2019-01-03"
              }
            }
          ]
        }
      }
    ]
  }
}

场景2:现在,如果您想了解在该确切时间段可用的用户列表,则范围查询将允许一个名为{{ 1}},您可以提及relation,这只会为您提供在特定时间范围内可用的候选人。

  

范围字段上的范围查询支持一个关系参数,该参数可以   成为WITHIN,CONTAINS,INTERSECTS(默认值)之一。

contains

让我知道这是否有帮助!