Elasticsearch按部分日期过滤

时间:2014-06-03 08:51:44

标签: elasticsearch

问题也许任何人都有解决方案如何按月或按天过滤/查询ElasticSearch数据?假设我需要今天庆祝生日的所有用户。

映射


mappings:
    dob: { type: date, format: "dd-MM-yyyy HH:mm:ss||yyyy-MM-dd'T'HH:mm:ss'Z'||yyyy-MM-dd'T'HH:mm:ss+SSSS"}

并以这种方式存储:

 dob: 1950-06-03T00:00:00Z 

主要问题是如何按月和日搜索用户。忽略这一年,因为生日是我们所知道的每年。


我找到了使用通配符查询生日的解决方案。我们知道如果我们想要使用通配符,则字段的映射必须是字符串,因此我使用了多字段映射。


mappings:
    dob:
        type: multi_field
        fields:
            dob: { type: date, format: "yyyy-MM-dd'T'HH:mm:ss'Z'}
            string: { type: string, index: not_analyzed }

以及仅按月和日获取用户的查询是:

{
    "query": {
        "wildcard": {
            "dob.string": "*-06-03*"
        }
    }
}

注意 此查询可能很慢,因为它需要迭代许多术语。

结论 这不是很好的方式,但它是我发现的唯一一个有效的方法!

3 个答案:

答案 0 :(得分:2)

根据您的问题,我假设您需要查询,而不是过滤器(它们不同),您可以使用日期数学/格式与范围查询相结合。

请参阅:range query了解用法

有关日期数学的说明,请参阅以下link

curl -XPOST http://localhost:9200/twitter/tweet/_search -d

{
  "query": {
    "range": {
        "birthday": {
            "gte" : "2014-01-01",
            "lte" : "2014-01-01"
        }
    }
  }
}

我使用最新的弹性搜索对此进行了测试。

答案 1 :(得分:1)

您应该在Elasticsearch中存储要搜索的值。字符串/通配符解决方案只有一半,但存储数字会更好(也更快):

mappings:
    dob:
        type: date, format: "yyyy-MM-dd'T'HH:mm:ss'Z'
    dob_day:
        type: byte
    dob_month:
        type: byte

示例:

dob: 1950-03-06
dob_day: 06
dob_month: 03

过滤(或查询)普通数字很容易:在两个字段上匹配。

  "query": {
    "filtered": {
      "filter": {
        "bool": {
          "must": [
            {
              "term": {
                "dob_day": 06,
              }
            },
            {
              "term": {
                "dob_month": 03,
              }
            },
          ]
        }
      }
    }
  }

PS:在考虑解决方案的同时:将日期存储为自我合并的数字,如" 06-03" - > " 603"或" 6.03"不太明显,但允许使用范围查询。但请记住,531(05-31)加上一天将是601(06-01)。

手动计算的朱利安日期也可能很方便,但计算必须假定2月为29天,如果范围包含2月29日,则范围查询有可能被忽略。

答案 2 :(得分:0)

如果您不想解析字符串,可以使用简单的脚本。当dateField在任何一年中具有特定月份时,此过滤器将匹配:

"filter": {
    "script": {
        "lang":   "expression",
        "script": "doc['dateField'].getMonth() == month",
        "params": {
            "month": 05,
        }
    }
}

注意:month参数为0索引。

相同的方法适用于某一天或任何其他日期组件。