范围字段类型

编辑

范围字段类型表示上下限之间连续的值范围。例如,一个范围可以表示十月份的任何日期从 0 到 9 的任何整数。它们使用运算符 gtgte 定义下限,并使用 ltlte 定义上限。它们可以用于查询,并且对聚合的支持有限。唯一支持的聚合是 直方图基数

支持以下范围类型

integer_range

带符号 32 位整数的范围,最小值为 -231,最大值为 231-1

float_range

单精度 32 位 IEEE 754 浮点值的范围。

long_range

带符号 64 位整数的范围,最小值为 -263,最大值为 263-1

double_range

双精度 64 位 IEEE 754 浮点值的范围。

date_range

date 值的范围。日期范围通过 format 映射参数支持各种日期格式。无论使用哪种格式,日期值都会被解析为自 Unix 纪元以来以 UTC 毫秒为单位的无符号 64 位整数。不支持包含 now 日期数学 表达式的值。

ip_range

支持 IPv4IPv6(或混合)地址的 IP 值范围。

以下是一个配置带有各种范围字段的映射的示例,然后是一个索引多个范围类型的示例。

resp = client.indices.create(
    index="range_index",
    settings={
        "number_of_shards": 2
    },
    mappings={
        "properties": {
            "expected_attendees": {
                "type": "integer_range"
            },
            "time_frame": {
                "type": "date_range",
                "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
            }
        }
    },
)
print(resp)

resp1 = client.index(
    index="range_index",
    id="1",
    refresh=True,
    document={
        "expected_attendees": {
            "gte": 10,
            "lt": 20
        },
        "time_frame": {
            "gte": "2015-10-31 12:00:00",
            "lte": "2015-11-01"
        }
    },
)
print(resp1)
response = client.indices.create(
  index: 'range_index',
  body: {
    settings: {
      number_of_shards: 2
    },
    mappings: {
      properties: {
        expected_attendees: {
          type: 'integer_range'
        },
        time_frame: {
          type: 'date_range',
          format: 'yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis'
        }
      }
    }
  }
)
puts response

response = client.index(
  index: 'range_index',
  id: 1,
  refresh: true,
  body: {
    expected_attendees: {
      gte: 10,
      lt: 20
    },
    time_frame: {
      gte: '2015-10-31 12:00:00',
      lte: '2015-11-01'
    }
  }
)
puts response
const response = await client.indices.create({
  index: "range_index",
  settings: {
    number_of_shards: 2,
  },
  mappings: {
    properties: {
      expected_attendees: {
        type: "integer_range",
      },
      time_frame: {
        type: "date_range",
        format: "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis",
      },
    },
  },
});
console.log(response);

const response1 = await client.index({
  index: "range_index",
  id: 1,
  refresh: "true",
  document: {
    expected_attendees: {
      gte: 10,
      lt: 20,
    },
    time_frame: {
      gte: "2015-10-31 12:00:00",
      lte: "2015-11-01",
    },
  },
});
console.log(response1);
PUT range_index
{
  "settings": {
    "number_of_shards": 2
  },
  "mappings": {
    "properties": {
      "expected_attendees": {
        "type": "integer_range"
      },
      "time_frame": {
        "type": "date_range", 
        "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
      }
    }
  }
}

PUT range_index/_doc/1?refresh
{
  "expected_attendees" : { 
    "gte" : 10,
    "lt" : 20
  },
  "time_frame" : {
    "gte" : "2015-10-31 12:00:00", 
    "lte" : "2015-11-01"
  }
}

date_range 类型接受 date 类型定义的相同字段参数。

示例:索引一个有 10 到 20 名参与者的会议,不包括 20 名。

示例:使用日期时间戳的日期范围。

以下是在名为“expected_attendees”的 integer_range 字段上的 Term 查询 的示例。12 是范围内的值,因此它将匹配。

resp = client.search(
    index="range_index",
    query={
        "term": {
            "expected_attendees": {
                "value": 12
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'range_index',
  body: {
    query: {
      term: {
        expected_attendees: {
          value: 12
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "range_index",
  query: {
    term: {
      expected_attendees: {
        value: 12,
      },
    },
  },
});
console.log(response);
GET range_index/_search
{
  "query" : {
    "term" : {
      "expected_attendees" : {
        "value": 12
      }
    }
  }
}

上述查询产生的结果。

{
  "took": 13,
  "timed_out": false,
  "_shards" : {
    "total": 2,
    "successful": 2,
    "skipped" : 0,
    "failed": 0
  },
  "hits" : {
    "total" : {
        "value": 1,
        "relation": "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "range_index",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "expected_attendees" : {
            "gte" : 10, "lt" : 20
          },
          "time_frame" : {
            "gte" : "2015-10-31 12:00:00", "lte" : "2015-11-01"
          }
        }
      }
    ]
  }
}

以下是在名为“time_frame”的 date_range 字段上的 date_range 查询的示例。

resp = client.search(
    index="range_index",
    query={
        "range": {
            "time_frame": {
                "gte": "2015-10-31",
                "lte": "2015-11-01",
                "relation": "within"
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'range_index',
  body: {
    query: {
      range: {
        time_frame: {
          gte: '2015-10-31',
          lte: '2015-11-01',
          relation: 'within'
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "range_index",
  query: {
    range: {
      time_frame: {
        gte: "2015-10-31",
        lte: "2015-11-01",
        relation: "within",
      },
    },
  },
});
console.log(response);
GET range_index/_search
{
  "query" : {
    "range" : {
      "time_frame" : { 
        "gte" : "2015-10-31",
        "lte" : "2015-11-01",
        "relation" : "within" 
      }
    }
  }
}

范围查询的工作方式与 范围查询 中描述的相同。

范围 字段上的范围查询支持 relation 参数,该参数可以是 WITHINCONTAINSINTERSECTS(默认)。

此查询产生类似的结果

{
  "took": 13,
  "timed_out": false,
  "_shards" : {
    "total": 2,
    "successful": 2,
    "skipped" : 0,
    "failed": 0
  },
  "hits" : {
    "total" : {
        "value": 1,
        "relation": "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "range_index",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "expected_attendees" : {
            "gte" : 10, "lt" : 20
          },
          "time_frame" : {
            "gte" : "2015-10-31 12:00:00", "lte" : "2015-11-01"
          }
        }
      }
    ]
  }
}

IP 范围

编辑

除了上面的范围格式之外,IP 范围还可以使用 CIDR 表示法提供

resp = client.indices.put_mapping(
    index="range_index",
    properties={
        "ip_allowlist": {
            "type": "ip_range"
        }
    },
)
print(resp)

resp1 = client.index(
    index="range_index",
    id="2",
    document={
        "ip_allowlist": "192.168.0.0/16"
    },
)
print(resp1)
response = client.indices.put_mapping(
  index: 'range_index',
  body: {
    properties: {
      ip_allowlist: {
        type: 'ip_range'
      }
    }
  }
)
puts response

response = client.index(
  index: 'range_index',
  id: 2,
  body: {
    ip_allowlist: '192.168.0.0/16'
  }
)
puts response
const response = await client.indices.putMapping({
  index: "range_index",
  properties: {
    ip_allowlist: {
      type: "ip_range",
    },
  },
});
console.log(response);

const response1 = await client.index({
  index: "range_index",
  id: 2,
  document: {
    ip_allowlist: "192.168.0.0/16",
  },
});
console.log(response1);
PUT range_index/_mapping
{
  "properties": {
    "ip_allowlist": {
      "type": "ip_range"
    }
  }
}

PUT range_index/_doc/2
{
  "ip_allowlist" : "192.168.0.0/16"
}

范围字段的参数

编辑

范围类型接受以下参数

coerce

尝试将字符串转换为数字,并为整数截断小数。接受 true (默认) 和 false

doc_values

是否应将字段以列式方式存储在磁盘上,以便以后可以用于排序、聚合或脚本?接受 true (默认) 或 false

index

该字段是否应该可搜索?接受 true (默认) 和 false

store

是否应存储字段值并可以从 _source 字段单独检索。接受 truefalse (默认)。

合成 _source

编辑

仅对于 TSDB 索引(index.mode 设置为 time_series 的索引),合成 _source 是正式可用的。对于其他索引,合成 _source 处于技术预览状态。技术预览版中的功能可能会在将来的版本中更改或删除。Elastic 将努力解决任何问题,但技术预览版中的功能不受官方 GA 功能的支持 SLA 约束。

range 字段在其默认配置中支持 合成 _source

合成源可以对 range 字段值进行排序并删除除 ip_range 之外的所有 range 字段的重复项。范围按其下限排序,然后按上限排序。例如

resp = client.indices.create(
    index="idx",
    settings={
        "index": {
            "mapping": {
                "source": {
                    "mode": "synthetic"
                }
            }
        }
    },
    mappings={
        "properties": {
            "my_range": {
                "type": "long_range"
            }
        }
    },
)
print(resp)

resp1 = client.index(
    index="idx",
    id="1",
    document={
        "my_range": [
            {
                "gte": 200,
                "lte": 300
            },
            {
                "gte": 1,
                "lte": 100
            },
            {
                "gte": 200,
                "lte": 300
            },
            {
                "gte": 200,
                "lte": 500
            }
        ]
    },
)
print(resp1)
const response = await client.indices.create({
  index: "idx",
  settings: {
    index: {
      mapping: {
        source: {
          mode: "synthetic",
        },
      },
    },
  },
  mappings: {
    properties: {
      my_range: {
        type: "long_range",
      },
    },
  },
});
console.log(response);

const response1 = await client.index({
  index: "idx",
  id: 1,
  document: {
    my_range: [
      {
        gte: 200,
        lte: 300,
      },
      {
        gte: 1,
        lte: 100,
      },
      {
        gte: 200,
        lte: 300,
      },
      {
        gte: 200,
        lte: 500,
      },
    ],
  },
});
console.log(response1);
PUT idx
{
  "settings": {
    "index": {
      "mapping": {
        "source": {
          "mode": "synthetic"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "my_range": { "type": "long_range" }
    }
  }
}

PUT idx/_doc/1
{
  "my_range": [
    {
        "gte": 200,
        "lte": 300
    },
    {
        "gte": 1,
        "lte": 100
    },
    {
        "gte": 200,
        "lte": 300
    },
    {
        "gte": 200,
        "lte": 500
    }
  ]
}

将变成

{
  "my_range": [
    {
        "gte": 1,
        "lte": 100
    },
    {
        "gte": 200,
        "lte": 300
    },
    {
        "gte": 200,
        "lte": 500
    }
  ]
}

ip_range 字段的值不会排序,但不会保留原始顺序。删除重复的范围。如果 ip_range 字段值以 CIDR 形式提供,则它将在合成源中表示为 IP 地址的范围。

例如

resp = client.indices.create(
    index="idx",
    settings={
        "index": {
            "mapping": {
                "source": {
                    "mode": "synthetic"
                }
            }
        }
    },
    mappings={
        "properties": {
            "my_range": {
                "type": "ip_range"
            }
        }
    },
)
print(resp)

resp1 = client.index(
    index="idx",
    id="1",
    document={
        "my_range": [
            "10.0.0.0/24",
            {
                "gte": "10.0.0.0",
                "lte": "10.0.0.255"
            }
        ]
    },
)
print(resp1)
const response = await client.indices.create({
  index: "idx",
  settings: {
    index: {
      mapping: {
        source: {
          mode: "synthetic",
        },
      },
    },
  },
  mappings: {
    properties: {
      my_range: {
        type: "ip_range",
      },
    },
  },
});
console.log(response);

const response1 = await client.index({
  index: "idx",
  id: 1,
  document: {
    my_range: [
      "10.0.0.0/24",
      {
        gte: "10.0.0.0",
        lte: "10.0.0.255",
      },
    ],
  },
});
console.log(response1);
PUT idx
{
  "settings": {
    "index": {
      "mapping": {
        "source": {
          "mode": "synthetic"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "my_range": { "type": "ip_range" }
    }
  }
}

PUT idx/_doc/1
{
  "my_range": [
    "10.0.0.0/24",
    {
      "gte": "10.0.0.0",
      "lte": "10.0.0.255"
    }
  ]
}

将变成

{
  "my_range": {
      "gte": "10.0.0.0",
      "lte": "10.0.0.255"
    }

}

范围字段值始终表示为两侧都包含,并会相应地调整边界。范围边界的默认值表示为 null。即使显式提供了范围边界,也是如此。例如

resp = client.indices.create(
    index="idx",
    settings={
        "index": {
            "mapping": {
                "source": {
                    "mode": "synthetic"
                }
            }
        }
    },
    mappings={
        "properties": {
            "my_range": {
                "type": "long_range"
            }
        }
    },
)
print(resp)

resp1 = client.index(
    index="idx",
    id="1",
    document={
        "my_range": {
            "gt": 200,
            "lt": 300
        }
    },
)
print(resp1)
const response = await client.indices.create({
  index: "idx",
  settings: {
    index: {
      mapping: {
        source: {
          mode: "synthetic",
        },
      },
    },
  },
  mappings: {
    properties: {
      my_range: {
        type: "long_range",
      },
    },
  },
});
console.log(response);

const response1 = await client.index({
  index: "idx",
  id: 1,
  document: {
    my_range: {
      gt: 200,
      lt: 300,
    },
  },
});
console.log(response1);
PUT idx
{
  "settings": {
    "index": {
      "mapping": {
        "source": {
          "mode": "synthetic"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "my_range": { "type": "long_range" }
    }
  }
}

PUT idx/_doc/1
{
  "my_range": {
    "gt": 200,
    "lt": 300
  }
}

将变成

{
  "my_range": {
    "gte": 201,
    "lte": 299
  }
}

范围边界的默认值在合成源中表示为 null。即使显式提供了带有默认值的范围边界,也是如此。例如

resp = client.indices.create(
    index="idx",
    settings={
        "index": {
            "mapping": {
                "source": {
                    "mode": "synthetic"
                }
            }
        }
    },
    mappings={
        "properties": {
            "my_range": {
                "type": "integer_range"
            }
        }
    },
)
print(resp)

resp1 = client.index(
    index="idx",
    id="1",
    document={
        "my_range": {
            "lte": 2147483647
        }
    },
)
print(resp1)
const response = await client.indices.create({
  index: "idx",
  settings: {
    index: {
      mapping: {
        source: {
          mode: "synthetic",
        },
      },
    },
  },
  mappings: {
    properties: {
      my_range: {
        type: "integer_range",
      },
    },
  },
});
console.log(response);

const response1 = await client.index({
  index: "idx",
  id: 1,
  document: {
    my_range: {
      lte: 2147483647,
    },
  },
});
console.log(response1);
PUT idx
{
  "settings": {
    "index": {
      "mapping": {
        "source": {
          "mode": "synthetic"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "my_range": { "type": "integer_range" }
    }
  }
}

PUT idx/_doc/1
{
  "my_range": {
    "lte": 2147483647
  }
}

将变成

{
  "my_range": {
    "gte": null,
    "lte": null
  }
}

date 范围使用提供的 format 或默认情况下使用 yyyy-MM-dd'T'HH:mm:ss.SSSZ 格式进行格式化。例如

resp = client.indices.create(
    index="idx",
    settings={
        "index": {
            "mapping": {
                "source": {
                    "mode": "synthetic"
                }
            }
        }
    },
    mappings={
        "properties": {
            "my_range": {
                "type": "date_range"
            }
        }
    },
)
print(resp)

resp1 = client.index(
    index="idx",
    id="1",
    document={
        "my_range": [
            {
                "gte": 1504224000000,
                "lte": 1504569600000
            },
            {
                "gte": "2017-09-01",
                "lte": "2017-09-10"
            }
        ]
    },
)
print(resp1)
const response = await client.indices.create({
  index: "idx",
  settings: {
    index: {
      mapping: {
        source: {
          mode: "synthetic",
        },
      },
    },
  },
  mappings: {
    properties: {
      my_range: {
        type: "date_range",
      },
    },
  },
});
console.log(response);

const response1 = await client.index({
  index: "idx",
  id: 1,
  document: {
    my_range: [
      {
        gte: 1504224000000,
        lte: 1504569600000,
      },
      {
        gte: "2017-09-01",
        lte: "2017-09-10",
      },
    ],
  },
});
console.log(response1);
PUT idx
{
  "settings": {
    "index": {
      "mapping": {
        "source": {
          "mode": "synthetic"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "my_range": { "type": "date_range" }
    }
  }
}

PUT idx/_doc/1
{
  "my_range": [
    {
      "gte": 1504224000000,
      "lte": 1504569600000
    },
    {
      "gte": "2017-09-01",
      "lte": "2017-09-10"
    }
  ]
}

将变成

{
  "my_range": [
    {
      "gte": "2017-09-01T00:00:00.000Z",
      "lte": "2017-09-05T00:00:00.000Z"
    },
    {
      "gte": "2017-09-01T00:00:00.000Z",
      "lte": "2017-09-10T23:59:59.999Z"
    }
  ]
}