弹性的文档日期比较问题

时间:2018-02-23 15:33:39

标签: elasticsearch elasticsearch-2.0

我有一个包含数千个此类文档的弹性索引。

{
    Name: John Doe,
    FirstJobStartDate: 8/9/2016,
    FirstJobEndDate:1/4/2019,
    SecondJobStartDate:7/4/2019,
    SecondJobEndDate:8/8/2020,
    ThirdJobStartDate: 1/9/2020,
}

除姓名& FirstJobStartDate,任何其他字段都是可选的,可能存在也可能不存在于doc中。

我需要获得4个数字:

1)有多少个文档有FirstJobEndDate?  这很容易

{
  "size":1,    
  "query": {
    "filtered": {
      "filter": {
        "bool": {
          "must": [
            {
              "exists": {
                "field": "FirstJobEndDate"
              }
            }
          ]
        }
      }
    }
  }
}

现在变得复杂了:

2)有多少文档的FirstJobEndDate小于当前日期,并且它们没有(SecondJobStartDate,SecondJobEndDate或ThirdJobStartDate)?

3)有多少文档有FirstJobEndDate,也有(SecondJobStartDate,SecondJobEndDate,ThirdJobStartDate)中的任何一个,其中任何一个日期都在FirstJobEndDate的1年内?

4)有多少文档有FirstJobEndDate,还有(SecondJobStartDate,SecondJobEndDate,ThirdJobStartDate)中的任何一个,而且这些日期中的NONE都在FirstJobEndDate的1年内?

我相信这可以通过'must'和'should'的正确组合来完成,但由于同一文档中两个日期之间的比较,无法获得任何明确的解决方案。

要确认,所有日期都是有效的弹性日期类型字段,而不是字符串。

非常感谢任何帮助。 弹性版本:2.4

1 个答案:

答案 0 :(得分:1)

试试这些:

对于第二个查询:

{
  "size": 1,
  "query": {
    "bool": {
      "filter": [
        {
          "exists": {
            "field": "FirstJobEndDate"
          }
        }
      ],
      "must_not": [
        {
          "exists": {
            "field": "SecondJobStartDate"
          }
        },
        {
          "exists": {
            "field": "SecondJobEndDate"
          }
        },
        {
          "exists": {
            "field": "ThirdJobStartDate"
          }
        }
      ]
    }
  }
}

对于第三个查询:

{
  "size": 1,
  "query": {
    "bool": {
      "filter": [
        {
          "exists": {
            "field": "FirstJobEndDate"
          }
        }
      ],
      "minimum_should_match": 1,
      "should": [
        {
          "script": {
            "script": "doc.SecondJobStartDate.date != null && doc.SecondJobStartDate.date.getMillis() - doc.FirstJobEndDate.date.getMillis() <= 31540000000"
          }
        },
        {
          "script": {
            "script": "doc.SecondJobEndDate.date != null && doc.SecondJobEndDate.date.getMillis() - doc.FirstJobEndDate.date.getMillis() <= 31540000000"
          }
        },
        {
          "script": {
            "script": "doc.ThirdJobStartDate.date != null && doc.ThirdJobStartDate.date.getMillis() - doc.FirstJobEndDate.date.getMillis() <= 31540000000"
          }
        }
      ]
    }
  }
}

对于第四个查询:

{
  "size": 1,
  "query": {
    "bool": {
      "filter": [
        {
          "exists": {
            "field": "FirstJobEndDate"
          }
        }
      ],
      "must_not": [
        {
          "script": {
            "script": "doc.SecondJobStartDate.date != null && doc.SecondJobStartDate.date.getMillis() - doc.FirstJobEndDate.date.getMillis() <= 31540000000"
          }
        },
        {
          "script": {
            "script": "doc.SecondJobEndDate.date != null && doc.SecondJobEndDate.date.getMillis() - doc.FirstJobEndDate.date.getMillis() <= 31540000000"
          }
        },
        {
          "script": {
            "script": "doc.ThirdJobStartDate.date != null && doc.ThirdJobStartDate.date.getMillis() - doc.FirstJobEndDate.date.getMillis() <= 31540000000"
          }
        }
      ]
    }
  }
}

只是一个提示:正如您所看到的,您需要利用脚本,这可能会影响性能。由于您事先知道要比较哪些日期,因此应将日期差异存储在其他标量字段中,以后可以轻松地与range查询进行比较。