elasticsearch学习10--Term-level queries之Range query

一、对日期字段的范围查询

在学习本文之前,请先参考【elasticsearch学习9–Term-level queries简介、term query与terms query】完成 blogs_index 索引的创建,同时批量导入如下数据:

POST _bulk
{"index":{"_index":"blogs_index","_type":"_doc","_id":"1"}}
{"id":1,"author":"大衣哥","title":"昨日博客","influence":{"gte":10,"lte":15},"createAt":"2020-05-24T10:56:23Z"}
{"index":{"_index":"blogs_index","_type":"_doc","_id":"2"}}
{"id":2,"author":"大衣哥","title":"今日博客","influence":{"gte":10,"lte":20},"createAt":"2020-05-25T10:56:23Z"}
{"index":{"_index":"blogs_index","_type":"_doc","_id":"3"}}
{"id":3,"author":"大衣哥","title":"一周内的博客","influence":{"gte":15,"lte":18},"createAt":"2020-05-18T10:56:23Z"}
{"index":{"_index":"blogs_index","_type":"_doc","_id":"4"}}
{"id":4,"author":"大衣哥","title":"一周外的博客","influence":{"gte":15,"lt":18},"createAt":"2020-05-17T10:56:23Z"}
{"index":{"_index":"blogs_index","_type":"_doc","_id":"5"}}
{"id":5,"author":"大衣哥","title":"上月博客","influence":{"gt":15,"lt":18},"createAt":"2020-04-26T10:56:23Z"}

gte 大于或等于
gt 大于
lte 小于或等于
lt 小于

1、Date Math 详解

Date Math 由两部分组成:
1)以固定的日期开头,这个固定的日期也可以是 now 或者是以“||”结尾的时间字符串;

例如:

2020-05-20 12:23:22
now
2020-05-20||(2020-05-20是字符串)

2)固定日期后面可接一个或多个数学表达式。
例如:

+1h:增加一小时
-1d:减少一天
/d:四舍五入到最近一天

支持的时间单位有:y-Years、M-Months、w-Weeks、d-Days、h-Hours、H-Hours、m-Minutes、s-Seconds

看几个Date Math 示例加以理解,比如当前时间:now = 2020-05-26 13:00:00

  • now + 1h :now的毫秒值 + 1小时,结果为:2020-05-26 14:00:00
  • now - 1h/d:now的毫秒值 - 1小时,再根据情况四舍五入到最近的一天的起始:2020-05-26 00:00:00 或者 结束:2020-05-26 23:59:59.999
  • 2020-05-26||-1M/M:2020-05-26 的毫秒值 - 1个月,再根据情况四舍五入到最近的一月的起始:2020-04-01 00:00:00 或者 结束:2020-04-30 23:59:59.999

这里的根据情况就是下面要介绍的 date math to round

2、date math to round

当使用date math 将日期四舍五入到最接近的日期、月份、小时等的时候,四舍五入的日期取决于范围的结尾是包含端点还是排除端点。

1)包含端点:按最大范围四舍五入

gte 大于或等于四舍五入的日期:2020-05-25||/M变为 2020-05-01,即包括整个月份。

POST /blogs_index/_search
{
    "query": {
        "range" : {
            "createAt" : {
                "gte" : "2020-05-25||/M"
            }
        }
    }
}

结果分析:可以检索到文档1、2、3、4(检索结果过长,此处就不展示了,可自行验证)。等价于sql【where createAt >=“2020-05-01 00:00:00”】

lte 小于或等于四舍五入的日期:2020-05-25||/M变为2020-05-31T23:59:59.999,即包括整个月份。

POST /blogs_index/_search
{
    "query": {
        "range" : {
            "createAt" : {
                "lte" : "2020-05-01||/M"
            }
        }
    }
}

结果分析:可以检索到所有文档(检索结果过长,此处就不展示了,可自行验证)。等价于sql【where createAt <=“2020-05-31 23:59:59.999”】

2)排除端点:按最小范围四舍五入

gt 大于四舍五入的日期:2020-05-01||/M 变为 2020-05-31T23:59:59.999,即排除整个月份。

POST /blogs_index/_search
{
    "query": {
        "range" : {
            "createAt" : {
                "gt" : "2020-05-01||/M"
            }
        }
    }
}

结果分析:检索不到任何文档。等价于sql【where createAt > “2020-05-31T23:59:59.999”】

lt 少于四舍五入的日期:2020-05-31||/M变为2020-05-01,即排除整个月份。

POST /blogs_index/_search
{
    "query": {
        "range" : {
            "createAt" : {
                "lt" : "2020-05-31||/M"
            }
        }
    }
}

结果分析:可以检索到文档5。等价于sql【where createAt < “2020-05-01 00:00:00”】

总结:
gte(大于等于)和lte(小于等于)会尽量包含,按最大范围四舍五入
gt(大于)和lt(小于)会尽量排除,按最小范围四舍五入

3、使用 Date Math 进行检索

ps:以下示例,基于now = 2020-05-25 23:00:00

1) 获取昨天发布的博客

POST /blogs_index/_search
{
    "query": {
        "range" : {
            "createAt" : {
                "gte" : "now-1d/d",
               "lt" :  "now/d"
            }
        }
    }
}

结果分析:可以检索到文档1【“title”: “昨日博客”】,等价于sql【where createAt >= “2020-05-24 00:00:00” and createAt < “2020-05-25 00:00:00”】

2) 获取一周内发布的博客

POST /blogs_index/_search
{
    "query": {
        "range" : {
            "createAt" : {
                "gte" : "now-1w/d",
               "lt" :  "now/d"
            }
        }
    }
}

结果分析:可以检索到文档1【“title”: “昨日博客”】和文档3【“title”: “一周内的博客”,】,等价于sql【where createAt >= “2020-05-18 00:00:00” and createAt < “2020-05-25 00:00:00”】

3) 获取本月内发布的博客

POST /blogs_index/_search
{
    "query": {
        "range" : {
            "createAt" : {
                "gte" : "now/M",
               "lte" :  "now/M"
            }
        }
    }
}

结果分析:可以检索到文档1/2/3/4,等价于sql【where createAt >= “2020-05-01 00:00:00” and createAt < “2020-05-31 23:59:59.999”】

4、日期范围检索的其他研究

1)格式问题:format参数

对日期字段进行检索时,默认使用被检索字段的format,但是可以通过“format”参数覆盖

POST /blogs_index/_search
{
    "query": {
        "range" : {
            "createAt" : {
                "gte": "20/05/2020",
                "lte": "2021",
                "format": "dd/MM/yyyy||yyyy"
            }
        }
    }
}

结果分析:可以检索到文档1和文档2。等价于sql【where createAt >= “2020-05-20T00:00:00Z” and createAt < “2021-01-01T00:00:00.000Z” 】

注意1:如果没有 “format”,上述DSL执行将报parse_exception 异常,因为date类型默认只支持3种格式,请参见【elasticsearch学习1–需要注意的数据格式
注意2:如果日期缺少年,月和日的某些坐标,则丢失的部分将以unix time的开始(即1970年1月1日)填充 。
例如,当指定dd格式时,“gte” : 10 将使用翻译成1970-01-10T00:00:00.000Z。

2)时区问题:time_zone参数

将日期从另一个时区转换为UTC(世界协调时间)

POST /blogs_index/_search
{
    "query": {
        "range" : {
            "createAt" : {
                "gte": "2020-05-25T11:56:23",
                "lte": "now",
                "time_zone": "+02:00"
            }
        }
    }
}

结果分析:“gte”: “2020-05-25T11:56:23”, 该日期将转换为2020-05-25T09:56:23 UTC。
所以可以检索到文档2(它的"createAt" :“2020-05-25T10:56:23Z”),如果没有 “time_zone”: “+02:00”,就检索不到任何文档。

now不受time_zone参数的影响,它始终是当前系统时间(以UTC为单位)。但是,在使用日期数学舍入时(例如,使用向下舍入到最近的日期now/d),time_zone将考虑提供的值。

二、 对类型为 range 字段的查询

relation参数控制这两个范围值【一个是文档field的value,一个是检索范围】如何匹配

先把文档influence字段的value列出来,方便大家对比数据:

文档1【“gte”:10,“lte”:15】
文档2【“gte”:10,“lte”:20】
文档3【“gte”:15,“lte”:18】
文档4【“gte”:15,“lt”:18】
文档5【“gt”:15,“lt”:18】

1、WITHIN:文档的范围字段要完全在检索关键词的范围里

POST /blogs_index/_search
{
  "query" : {
    "range" : {
      "influence": {
        "gte" : 12,
        "lte" : 17,
        "relation" : "within"
      }
    }
  }
}

结果分析:可以检索到文档4和文档5,[15,18)和(15,18)完全在[12,17]范围里

2、CONTAINS:文档的范围字段完全包含检索关键词的范围

POST /blogs_index/_search
{
  "query" : {
    "range" : {
      "influence": {
        "gte" : 12,
        "lte" : 17,
        "relation" : "CONTAINS"
      }
    }
  }
}

结果分析:可以检索到文档2,只有[10,20]完全包含[12,17]范围

3、INTERSECTS(默认值):文档的范围字段与检索关键词的范围有交集即可

POST /blogs_index/_search
{
  "query" : {
    "range" : {
      "influence": {
        "gte" : 12,
        "lte" : 17,
        "relation" : "CONTAINS"
      }
    }
  }
}

结果分析:可以检索到所有文档,都有交集

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值