字段数据类型

edit

字段数据类型

edit

每个字段都有一个字段数据类型,或字段类型。这个类型指示了字段包含的数据种类,例如字符串或布尔值,以及其预期用途。例如,您可以将字符串索引到textkeyword字段中。然而,text字段值会进行分析以进行全文搜索,而keyword字符串则保持原样以进行过滤和排序。

字段类型按家族分组。同一家族中的类型具有完全相同的搜索行为,但可能在空间使用或性能特征上有所不同。

目前,有两种类型家族,keywordtext。其他类型家族只有一个字段类型。例如,boolean 类型家族由一个字段类型组成:boolean

常见类型

edit
binary
二进制值编码为Base64字符串。
boolean
truefalse 值。
Keywords
关键词家族,包括 keywordconstant_keywordwildcard
Numbers
数值类型,例如 longdouble,用于表示数量。
Dates
日期类型,包括 datedate_nanos
alias
定义现有字段的别名。

对象和关系类型

edit
object
一个JSON对象。
flattened
一个完整的JSON对象作为一个单一的字段值。
nested
一个保留其子字段之间关系的JSON对象。
join
定义同一索引中文档的父子关系。
passthrough
为同一级别的子字段提供别名。

结构化数据类型

edit
Range
范围类型,例如 long_rangedouble_rangedate_rangeip_range
ip
IPv4 和 IPv6 地址。
version
软件版本。支持 语义化版本控制 优先规则。
murmur3
计算并存储值的哈希值。

聚合数据类型

edit
aggregate_metric_double
预聚合的指标值。
histogram
以直方图形式预聚合的数值。

文本搜索类型

edit
text fields
文本系列,包括 textmatch_only_text。 分析过的、非结构化的文本。
annotated-text
包含特殊标记的文本。用于识别命名实体。
completion
用于自动完成建议。
search_as_you_type
text-类似类型用于 即时完成输入。
semantic_text
用于执行语义搜索
token_count
文本中标记的数量。

文档排名类型

edit
dense_vector
记录浮点值的密集向量。
sparse_vector
记录稀疏向量的浮点值。
rank_feature
记录一个数值特征以在查询时提升命中。
rank_features
记录数值特征以在查询时提升命中率。

空间数据类型

edit
geo_point
纬度和经度点。
geo_shape
复杂的形状,如多边形。
point
任意笛卡尔点。
shape
任意笛卡尔几何。

其他类型

edit
percolator
索引使用Query DSL编写的查询。

数组

edit

在Elasticsearch中,数组不需要专门的字段数据类型。默认情况下,任何字段都可以包含零个或多个值,但是数组中的所有值必须是相同的字段类型。请参阅数组

多字段

edit

对于不同的目的,通常有用的是以不同的方式索引同一个字段。例如,一个字符串字段可以映射为一个文本字段用于全文搜索,并且作为一个关键字字段用于排序或聚合。或者,你可以使用标准分析器英语分析器和法语分析器来索引一个文本字段。

这就是多字段的目的。大多数字段类型通过fields参数支持多字段。

聚合指标字段类型

edit

存储用于指标聚合的预聚合数值。一个aggregate_metric_double字段是一个包含一个或多个以下指标子字段的对象:minmaxsumvalue_count

当您对aggregate_metric_double字段运行某些指标聚合时, 聚合使用相关子字段的值。例如,对aggregate_metric_double字段进行 min聚合将返回所有min 子字段的最小值。

一个 aggregate_metric_double 字段为每个指标子字段存储一个单一的数值 文档值。不支持数组值。minmaxsum 值是 double 数字。value_count 是一个正的 long 数字。

PUT my-index
{
  "mappings": {
    "properties": {
      "my-agg-metric-field": {
        "type": "aggregate_metric_double",
        "metrics": [ "min", "max", "sum", "value_count" ],
        "default_metric": "max"
      }
    }
  }
}

aggregate_metric_double 字段的参数

edit
metrics
(必需,字符串数组) 要存储的度量子字段的数组。每个值对应一个 度量聚合。有效值为 min, max, sum, 和 value_count。你必须 指定至少一个值。
default_metric
(必需,字符串) 用于查询、脚本和聚合的默认度量子字段,当这些操作不使用子字段时。必须是从 metrics 数组中取的值。
time_series_metric

(可选,字符串) 将字段标记为时间序列指标。该值是指标类型。您不能更新现有字段的此参数。

适用于aggregate_metric_double字段的有效time_series_metric
gauge
表示可以任意增加或减少的单个数值的指标。例如,温度或可用磁盘空间。
null (默认)
不是时间序列指标。

用途

edit

我们设计了 aggregate_metric_double 字段,用于以下聚合:

  • 一个min聚合返回所有min子字段的最小值。
  • 一个max聚合返回所有max子字段的最大值。
  • 一个sum聚合返回所有sum子字段值的总和。
  • 一个value_count聚合返回所有value_count子字段值的总和。
  • 一个avg聚合。没有avg子字段;avg聚合的结果是使用sumvalue_count指标计算的。要运行一个avg聚合,字段必须包含sumvalue_count指标子字段。

aggregate_metric_double 字段运行任何其他聚合将失败,并显示“不支持的聚合”错误。

最后,一个 aggregate_metric_double 字段支持以下查询,它通过将其行为委托给其 default_metric 子字段,表现得像一个 double

示例

edit

以下创建索引 API 请求创建了一个包含名为 agg_metricaggregate_metric_double 字段的索引。该请求将 max 设置为字段的 default_metric

PUT stats-index
{
  "mappings": {
    "properties": {
      "agg_metric": {
        "type": "aggregate_metric_double",
        "metrics": [ "min", "max", "sum", "value_count" ],
        "default_metric": "max"
      }
    }
  }
}

以下索引 API 请求添加了包含预聚合数据的文档,数据位于 agg_metric 字段中。

PUT stats-index/_doc/1
{
  "agg_metric": {
    "min": -302.50,
    "max": 702.30,
    "sum": 200.0,
    "value_count": 25
  }
}

PUT stats-index/_doc/2
{
  "agg_metric": {
    "min": -93.00,
    "max": 1702.30,
    "sum": 300.00,
    "value_count": 25
  }
}

您可以在 agg_metric 字段上运行 minmaxsumvalue_countavg 聚合。

POST stats-index/_search?size=0
{
  "aggs": {
    "metric_min": { "min": { "field": "agg_metric" } },
    "metric_max": { "max": { "field": "agg_metric" } },
    "metric_value_count": { "value_count": { "field": "agg_metric" } },
    "metric_sum": { "sum": { "field": "agg_metric" } },
    "metric_avg": { "avg": { "field": "agg_metric" } }
  }
}

聚合结果基于相关指标子字段的值。

{
...
  "aggregations": {
    "metric_min": {
      "value": -302.5
    },
    "metric_max": {
      "value": 1702.3
    },
    "metric_value_count": {
      "value": 50
    },
    "metric_sum": {
      "value": 500.0
    },
    "metric_avg": {
      "value": 10.0
    }
  }
}

aggregate_metric_double 字段的查询使用 default_metric 值。

GET stats-index/_search
{
  "query": {
    "term": {
      "agg_metric": {
        "value": 702.30
      }
    }
  }
}

搜索返回了以下结果。default_metric 字段的值,max,与查询值匹配。

{
  ...
    "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 1.0,
    "hits": [
      {
        "_index": "stats-index",
        "_id": "1",
        "_score": 1.0,
        "_source": {
          "agg_metric": {
            "min": -302.5,
            "max": 702.3,
            "sum": 200.0,
            "value_count": 25
          }
        }
      }
    ]
  }
}

综合 _source

edit

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

例如:

PUT idx
{
  "settings": {
    "index": {
      "mapping": {
        "source": {
          "mode": "synthetic"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "agg_metric": {
        "type": "aggregate_metric_double",
        "metrics": [ "min", "max", "sum", "value_count" ],
        "default_metric": "max"
      }
    }
  }
}

PUT idx/_doc/1
{
  "agg_metric": {
    "min": -302.50,
    "max": 702.30,
    "sum": 200.0,
    "value_count": 25
  }
}

将变为:

{
  "agg_metric": {
    "min": -302.50,
    "max": 702.30,
    "sum": 200.0,
    "value_count": 25
  }
}

别名字段类型

edit

一个 alias 映射定义了索引中字段的替代名称。 该别名可以在 搜索 请求中代替目标字段使用, 并且可以在其他一些API中使用,例如 字段能力

PUT trips
{
  "mappings": {
    "properties": {
      "distance": {
        "type": "long"
      },
      "route_length_miles": {
        "type": "alias",
        "path": "distance" 
      },
      "transit_mode": {
        "type": "keyword"
      }
    }
  }
}

GET _search
{
  "query": {
    "range" : {
      "route_length_miles" : {
        "gte" : 39
      }
    }
  }
}

目标字段的路径。请注意,这必须是完整路径,包括任何父对象(例如 object1.object2.field)。

几乎所有搜索请求的组件都接受字段别名。特别是,别名可以用于查询、聚合、排序字段,以及在请求docvalue_fieldsstored_fields、建议和高亮时使用。脚本在访问字段值时也支持别名。请参阅不支持的API部分了解例外情况。

在搜索请求的某些部分以及请求字段能力时,可以提供字段通配符模式。在这些情况下,通配符模式将匹配字段别名以及具体字段:

GET trips/_field_caps?fields=route_*,transit_mode

别名目标

edit

关于别名的目标有一些限制:

  • 目标必须是一个具体字段,而不是对象或其他字段别名。
  • 目标字段必须在创建别名时存在。
  • 如果定义了嵌套对象,字段别名必须与其目标具有相同的嵌套范围。

此外,字段别名只能有一个目标。这意味着不能在单个子句中使用字段别名来查询多个目标字段。

可以通过映射更新将别名更改为引用新的目标。已知的一个限制是,如果任何存储的percolator查询包含该字段别名,它们仍将引用其原始目标。更多信息可以在percolator文档中找到。

不支持的API

edit

不支持写入字段别名:尝试在索引或更新请求中使用别名将导致失败。同样,别名不能用作copy_to的目标或在多字段中使用。

因为别名在文档源中不存在,所以在执行源过滤时不能使用别名。例如,以下请求将为_source返回空结果:

GET /_search
{
  "query" : {
    "match_all": {}
  },
  "_source": "route_length_miles"
}

目前只有搜索和字段能力API可以接受并解析字段别名。 其他接受字段名称的API,例如term vectors,不能与字段别名一起使用。

最后,一些查询,如termsgeo_shapemore_like_this,允许从索引文档中获取查询信息。由于在获取文档时不支持字段别名,因此指定查找路径的部分查询不能通过别名引用字段。

数组

edit

在Elasticsearch中,没有专门的数组数据类型。默认情况下,任何字段都可以包含零个或多个值,但是数组中的所有值必须具有相同的数据类型。例如:

  • 一个字符串数组:[ "one", "two" ]
  • 一个整数数组:[ 1, 2 ]
  • 一个数组的数组:[ 1, [ 2, 3 ]] 等同于 [ 1, 2, 3 ]
  • 一个对象数组:[ { "name": "Mary", "age": 12 }, { "name": "John", "age": 10 }]

对象数组

对象数组的工作方式可能与您的预期不同:您无法独立于数组中的其他对象查询每个对象。如果您需要能够这样做,那么您应该使用 nested 数据类型,而不是 object 数据类型。

这在嵌套中有更详细的解释。

当动态添加字段时,数组中的第一个值决定了字段的类型。所有后续值必须具有相同的数据类型,或者至少可以将后续值强制转换为相同的数据类型。

混合数据类型的数组支持:[ 10, "some string" ]

数组可能包含 null 值,这些值要么被配置的 null_value 替换,要么完全跳过。一个空数组 [] 被视为缺失字段——一个没有值的字段。

在文档中使用数组无需预先配置,它们是开箱即用的:

PUT my-index-000001/_doc/1
{
  "message": "some arrays in this document...",
  "tags":  [ "elasticsearch", "wow" ], 
  "lists": [ 
    {
      "name": "prog_list",
      "description": "programming list"
    },
    {
      "name": "cool_list",
      "description": "cool stuff list"
    }
  ]
}

PUT my-index-000001/_doc/2 
{
  "message": "no arrays in this document...",
  "tags":  "elasticsearch",
  "lists": {
    "name": "prog_list",
    "description": "programming list"
  }
}

GET my-index-000001/_search
{
  "query": {
    "match": {
      "tags": "elasticsearch" 
    }
  }
}

The tags 字段是动态添加为 string 字段。

The lists 字段是动态添加为 object 字段。

第二个文档不包含数组,但可以索引到相同的字段中。

查询在tags字段中查找elasticsearch,并匹配两个文档。

二进制字段类型

edit

The binary type accepts a binary value as a Base64 encoded string. The field is not stored by default and is not searchable:

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "name": {
        "type": "text"
      },
      "blob": {
        "type": "binary"
      }
    }
  }
}

PUT my-index-000001/_doc/1
{
  "name": "Some binary blob",
  "blob": "U29tZSBiaW5hcnkgYmxvYg==" 
}

Base64 编码的二进制值不得包含嵌入的换行符 \n

binary 字段的参数

edit

以下参数被binary字段接受:

doc_values

该字段是否应以列步长的方式存储在磁盘上,以便以后可以用于排序、聚合或脚本编写?接受 truefalse(默认)。对于TSDB索引(将 index.mode 设置为 time_series 的索引),此参数将自动设置为 true

store

字段值是否应与_source字段分开存储和检索。接受truefalse(默认)。

合成 _source

edit

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

合成源可能会按照字节表示的顺序对二进制值进行排序。例如:

PUT idx
{
  "mappings": {
    "_source": { "mode": "synthetic" },
    "properties": {
      "binary": { "type": "binary", "doc_values": true }
    }
  }
}
PUT idx/_doc/1
{
  "binary": ["IAA=", "EAA="]
}

将变为:

{
  "binary": ["EAA=", "IAA="]
}

布尔字段类型

edit

布尔字段接受 JSON truefalse 值,但也可以接受被解释为真或假的字符串:

假值

false, "false", ""(空字符串)

真值

true, "true"

例如:

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "is_published": {
        "type": "boolean"
      }
    }
  }
}

POST my-index-000001/_doc/1?refresh
{
  "is_published": "true" 
}

GET my-index-000001/_search
{
  "query": {
    "term": {
      "is_published": true 
    }
  }
}

将文档索引为"true",这被解释为true

搜索包含JSON true的文档。

聚合操作,如terms 聚合,使用10作为key,以及字符串"true""false"作为key_as_string。布尔字段在脚本中使用时, 返回truefalse

POST my-index-000001/_doc/1?refresh
{
  "is_published": true
}

POST my-index-000001/_doc/2?refresh
{
  "is_published": false
}

GET my-index-000001/_search
{
  "aggs": {
    "publish_state": {
      "terms": {
        "field": "is_published"
      }
    }
  },
  "sort": [ "is_published" ],
  "fields": [
    {"field": "weight"}
  ],
  "runtime_mappings": {
    "weight": {
      "type": "long",
      "script": "emit(doc['is_published'].value ? 10 : 0)"
    }
  }
}

布尔字段的参数

edit

以下参数被boolean字段接受:

doc_values

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

index

字段是否应快速可搜索?接受 true(默认)和 false。仅启用了 doc_values 的字段仍然可以使用术语或基于范围的查询进行查询, 尽管速度较慢。

ignore_malformed

尝试将错误的数据类型索引到字段中会默认抛出异常,并拒绝整个文档。如果此参数设置为true,则允许忽略该异常。格式错误的字段不会被索引,但文档中的其他字段会正常处理。接受truefalse。请注意,如果使用了script参数,则无法设置此参数。

null_value

接受上述任何真或假值。该值将替换任何显式的 null 值。默认为 null,这意味着该字段被视为缺失。请注意,如果使用了 script 参数,则不能设置此项。

on_script_error

定义如果在索引时由script参数定义的脚本抛出错误时应执行的操作。接受fail(默认),这将导致整个文档被拒绝,以及continue,这将把字段注册在文档的_ignored元数据字段中并继续索引。此参数只能在设置了script字段时设置。

脚本

如果设置了此参数,则该字段将索引由此脚本生成的值,而不是直接从源中读取值。如果在输入文档上为此字段设置了值,则文档将被拒绝并显示错误。 脚本的格式与其运行时等效项相同。

store

字段值是否应与_source字段分开存储和检索。接受truefalse(默认)。

meta

字段的元数据。

时间序列维度

(可选, 布尔值)

将字段标记为时间序列维度。默认为false

index.mapping.dimension_fields.limit 索引设置限制了索引中的维度数量。

维度字段具有以下约束:

  • doc_valuesindex 映射参数必须为 true

合成 _source

edit

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

布尔 字段在其默认配置中支持 synthetic _source

合成源可以对布尔字段值进行排序。例如:

PUT idx
{
  "settings": {
    "index": {
      "mapping": {
        "source": {
          "mode": "synthetic"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "bool": { "type": "boolean" }
    }
  }
}
PUT idx/_doc/1
{
  "bool": [true, false, true, false]
}

将变为:

{
  "bool": [false, false, true, true]
}

完成字段类型

edit

要使用completion suggester,请将您希望从中生成建议的字段映射为类型completion。这将索引字段值以实现快速完成。

PUT music
{
  "mappings": {
    "properties": {
      "suggest": {
        "type": "completion"
      }
    }
  }
}

用于completion字段的参数

edit

以下参数由 completion 字段接受:

analyzer

要使用的索引分析器,默认为 简单

search_analyzer

要使用的搜索分析器,默认为 analyzer 的值。

保留分隔符

保留分隔符,默认为 true。 如果禁用,你可能会找到一个以 Foo Fighters 开头的字段,如果你建议为 foof

preserve_position_increments

启用位置增量,默认为 true。 如果禁用并使用停用词分析器,您可能会得到一个以 The Beatles 开头的字段,如果您建议 b注意:您也可以通过索引两个输入 BeatlesThe Beatles 来实现这一点,如果您能够丰富您的数据,则无需更改简单的分析器。

max_input_length

限制单个输入的长度,默认为 50 个 UTF-16 代码点。 此限制仅在索引时使用,以减少每个输入字符串的总字符数,从而防止大量输入导致底层数据结构膨胀。大多数用例不会受到默认值的影响,因为前缀补全很少会超出几个字符长的前缀。

日期字段类型

edit

JSON 没有日期数据类型,因此在 Elasticsearch 中的日期可以是:

  • 包含格式化日期的字符串,例如 "2015-01-01""2015/01/01 12:10:30"
  • 表示自纪元以来的毫秒数的数字。
  • 表示自纪元以来的秒数的数字(配置)。

在内部,日期会被转换为UTC(如果指定了时区),并以表示自纪元以来的毫秒数的长数字形式存储。

如果需要纳秒级分辨率,请使用date_nanos字段类型。

日期查询在内部被转换为对此长整型表示的范围查询,并且聚合和存储字段的结果根据与字段关联的日期格式转换回字符串。

日期将始终以字符串形式呈现,即使它们最初在JSON文档中是以长整型提供的。

日期格式可以自定义,但如果未指定format,则使用默认格式:

    "strict_date_optional_time||epoch_millis"

这意味着它将接受带有可选时间戳的日期,这些日期符合strict_date_optional_time或自纪元以来的毫秒数所支持的格式。

例如:

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "date": {
        "type": "date" 
      }
    }
  }
}

PUT my-index-000001/_doc/1
{ "date": "2015-01-01" } 

PUT my-index-000001/_doc/2
{ "date": "2015-01-01T12:10:30Z" } 

PUT my-index-000001/_doc/3
{ "date": 1420070400001 } 

GET my-index-000001/_search
{
  "sort": { "date": "asc"} 
}

The date 字段使用默认的 format

本文档使用一个简单的日期。

本文档包含一个时间。

本文档使用自纪元以来的毫秒数。

请注意,返回的 sort 值都是自纪元以来的毫秒数。

日期 将接受带有小数点的数字,如 {"date": 1618249875.123456} 但在某些情况下(#70085),我们会丢失这些日期的精度,因此应避免使用。

多种日期格式

edit

可以通过使用 || 作为分隔符来指定多种格式。 每种格式将依次尝试,直到找到匹配的格式。第一个格式将用于将 自纪元以来的毫秒数 值转换回字符串。

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "date": {
        "type":   "date",
        "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
      }
    }
  }
}

date 字段的参数

edit

以下参数被date字段接受:

doc_values

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

format

可以解析的日期格式。默认为 strict_date_optional_time||epoch_millis

区域设置

用于解析日期时的区域设置,因为不同语言中月份的名称和/或缩写不同。默认值为英语。

ignore_malformed

如果 true,格式错误的数字将被忽略。如果 false(默认),格式错误的数字将抛出异常并拒绝整个文档。请注意,如果使用了 script 参数,则无法设置此选项。

index

该字段是否应快速可搜索?接受 true(默认)和 false。仅启用了 doc_values 的日期字段也可以查询,尽管速度较慢。

null_value

接受以配置的 format 之一表示的日期值作为字段,该字段将替换任何显式的 null 值。默认为 null,这意味着该字段被视为缺失。请注意,如果使用了 script 参数,则无法设置此项。

on_script_error

定义如果在索引时由script参数定义的脚本抛出错误时应执行的操作。接受fail(默认),这将导致整个文档被拒绝,以及continue,这将把字段注册在文档的_ignored元数据字段中并继续索引。此参数只能在设置了script字段时设置。

脚本

如果设置了此参数,则该字段将索引由此脚本生成的值,而不是直接从源读取值。如果在输入文档上为此字段设置了值,则文档将被拒绝并返回错误。脚本的格式与其运行时等效相同,并且应发出长值时间戳。

store

字段值是否应与_source字段分开存储和检索。接受truefalse(默认)。

meta

字段的元数据。

纪元秒

edit

如果你需要将日期发送为自纪元以来的秒数,请确保format列表中包含epoch_second

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "date": {
        "type":   "date",
        "format": "strict_date_optional_time||epoch_second"
      }
    }
  }
}

PUT my-index-000001/_doc/example?refresh
{ "date": 1618321898 }

POST my-index-000001/_search
{
  "fields": [ {"field": "date"}],
  "_source": false
}

这将回复一个类似以下的日期:

{
  "hits": {
    "hits": [
      {
        "_id": "example",
        "_index": "my-index-000001",
        "_score": 1.0,
        "fields": {
          "date": ["2021-04-13T13:51:38.000Z"]
        }
      }
    ]
  }
}

合成 _source

edit

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

合成源可能会对日期字段值进行排序。例如:

PUT idx
{
  "settings": {
    "index": {
      "mapping": {
        "source": {
          "mode": "synthetic"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "date": { "type": "date" }
    }
  }
}
PUT idx/_doc/1
{
  "date": ["2015-01-01T12:10:30Z", "2014-01-01T12:10:30Z"]
}

将变为:

{
  "date": ["2014-01-01T12:10:30.000Z", "2015-01-01T12:10:30.000Z"]
}

日期纳秒字段类型

edit

此数据类型是对 date 数据类型的补充。然而,两者之间有一个重要的区别。现有的 date 数据类型以毫秒分辨率存储日期。而 date_nanos 数据类型以纳秒分辨率存储日期,这限制了其日期范围大约从 1970 年到 2262 年,因为日期仍然存储为自纪元以来的纳秒数的长整型表示。

对纳秒的查询在内部被转换为对此长整型表示的范围查询,并且聚合和存储字段的结果根据与该字段关联的日期格式转换回字符串。

日期格式可以自定义,但如果未指定format,则使用默认格式:

    "strict_date_optional_time_nanos||epoch_millis"

例如:

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "date": {
        "type": "date_nanos" 
      }
    }
  }
}

PUT my-index-000001/_bulk?refresh
{ "index" : { "_id" : "1" } }
{ "date": "2015-01-01" } 
{ "index" : { "_id" : "2" } }
{ "date": "2015-01-01T12:10:30.123456789Z" } 
{ "index" : { "_id" : "3" } }
{ "date": 1420070400000 } 

GET my-index-000001/_search
{
  "sort": { "date": "asc"}, 
  "runtime_mappings": {
    "date_has_nanos": {
      "type": "boolean",
      "script": "emit(doc['date'].value.nano != 0)" 
    }
  },
  "fields": [
    {
      "field": "date",
      "format": "strict_date_optional_time_nanos" 
    },
    {
      "field": "date_has_nanos"
    }
  ]
}

The date 字段使用默认的 format

本文档使用一个简单的日期。

本文档包含一个时间。

本文档使用自纪元以来的毫秒数。

请注意,返回的 sort 值都是自纪元以来的纳秒数。

在脚本中使用.nano来返回日期的纳秒部分。

您可以在使用fields参数获取数据时指定格式。 使用strict_date_optional_time_nanos,否则您将得到一个四舍五入的结果。

您还可以指定多个日期格式,用||分隔。与date字段相同的映射参数也可以使用。

日期纳秒 将接受带有小数点的数字,如 {"date": 1618249875.123456} 但在某些情况下(#70085),我们会丢失这些日期的精度,因此应避免使用。

限制

edit

即使在使用 date_nanos 字段时,聚合仍然以毫秒为分辨率。这一限制也会影响 transforms


合成 _source

edit

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

合成源可能会对 date_nanos 字段值进行排序。例如:

PUT idx
{
  "settings": {
    "index": {
      "mapping": {
        "source": {
          "mode": "synthetic"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "date": { "type": "date_nanos" }
    }
  }
}
PUT idx/_doc/1
{
  "date": ["2015-01-01T12:10:30.000Z", "2014-01-01T12:10:30.000Z"]
}

将变为:

{
  "date": ["2014-01-01T12:10:30.000Z", "2015-01-01T12:10:30.000Z"]
}

密集向量字段类型

edit

The dense_vector 字段类型存储数值的密集向量。密集向量字段主要用于 k-nearest neighbor (kNN) search

The dense_vector 类型不支持聚合或排序。

您添加一个 dense_vector 字段作为基于 element_type 的数值数组,默认情况下使用 float

PUT my-index
{
  "mappings": {
    "properties": {
      "my_vector": {
        "type": "dense_vector",
        "dims": 3
      },
      "my_text" : {
        "type" : "keyword"
      }
    }
  }
}

PUT my-index/_doc/1
{
  "my_text" : "text1",
  "my_vector" : [0.5, 10, 6]
}

PUT my-index/_doc/2
{
  "my_text" : "text2",
  "my_vector" : [-0.5, 10, 10]
}

与大多数其他数据类型不同,密集向量始终是单值的。 无法在一个dense_vector字段中存储多个值。

用于kNN搜索的索引向量

edit

一个k近邻(kNN)搜索找到与查询向量最接近的k个向量,通过相似性度量来衡量。

密集向量场可以用于在script_score查询中对文档进行排序。这使您可以通过扫描所有文档并根据相似性对它们进行排序来执行暴力kNN搜索。

在许多情况下,暴力kNN搜索效率不够高。因此,dense_vector类型支持将向量索引到一种特殊的数据结构中,以通过搜索API中的knn选项支持快速kNN检索。

大小在128到4096之间的未映射浮点数组字段会动态映射为dense_vector,默认相似度为cosine。 您可以通过显式地将字段映射为dense_vector并指定所需的相似度来覆盖默认相似度。

默认情况下,密集向量字段启用索引,并被索引为int8_hnsw。 当启用索引时,您可以在kNN搜索中定义要使用的向量相似度:

PUT my-index-2
{
  "mappings": {
    "properties": {
      "my_vector": {
        "type": "dense_vector",
        "dims": 3,
        "similarity": "dot_product"
      }
    }
  }
}

对向量进行索引以进行近似kNN搜索是一个昂贵的过程。对于包含启用了index的向量字段的文档,摄取这些文档可能需要大量时间。请参阅k-最近邻(kNN)搜索以了解更多关于内存需求的信息。

您可以通过将 index 参数设置为 false 来禁用索引:

PUT my-index-2
{
  "mappings": {
    "properties": {
      "my_vector": {
        "type": "dense_vector",
        "dims": 3,
        "index": false
      }
    }
  }
}

Elasticsearch 使用 HNSW 算法 来支持高效的 kNN 搜索。与大多数 kNN 算法一样,HNSW 是一种近似方法,它牺牲了结果的准确性以提高速度。

自动量化向量以进行kNN搜索

edit

The dense_vector type supports quantization to reduce the memory footprint required when searching float vectors. The three following quantization strategies are supported:

+

int8 - 将向量的每个维度量化为1字节整数。这会以一定的精度为代价,将内存占用减少75%(或4倍)。 int4 - 将向量的每个维度量化为半字节整数。这会以一定的精度为代价,将内存占用减少87%(或8倍)。 bbq - [预览] 此功能处于技术预览阶段,可能会在未来的版本中更改或删除。Elastic将努力修复任何问题,但技术预览中的功能不受官方GA功能支持SLA的约束。 更好的二进制量化,将每个维度减少到单个比特精度。这会以更大的精度为代价,将内存占用减少96%(或32倍)。通常,在查询期间进行过采样和重新排序可以帮助缓解精度损失。

在使用量化格式时,您可能希望对结果进行过采样和重新评分以提高准确性。有关更多信息,请参阅过采样和重新评分

要使用量化索引,您可以将索引类型设置为int8_hnswint4_hnswbbq_hnsw。当索引float向量时,当前默认的索引类型是int8_hnsw

量化将继续在磁盘上保留原始浮点向量值,以便在数据的生命周期内进行重新排序、重新索引和量化改进。 这意味着由于存储量化和原始向量的开销,磁盘使用量将增加约25%用于int8,约12.5%用于int4,以及约3.1%用于bbq

int4 量化需要偶数维的向量。

[预览] 此功能处于技术预览阶段,可能会在未来的版本中更改或删除。Elastic 将努力修复任何问题,但技术预览中的功能不受官方 GA 功能支持 SLA 的约束。 bbq 量化仅支持大于 64 的向量维度。

这里是一个如何创建字节量化索引的示例:

PUT my-byte-quantized-index
{
  "mappings": {
    "properties": {
      "my_vector": {
        "type": "dense_vector",
        "dims": 3,
        "index": true,
        "index_options": {
          "type": "int8_hnsw"
        }
      }
    }
  }
}

这是一个如何创建半字节量化索引的示例:

PUT my-byte-quantized-index
{
  "mappings": {
    "properties": {
      "my_vector": {
        "type": "dense_vector",
        "dims": 4,
        "index": true,
        "index_options": {
          "type": "int4_hnsw"
        }
      }
    }
  }
}

[预览] 此功能处于技术预览阶段,可能会在未来的版本中进行更改或移除。Elastic 将努力修复任何问题,但技术预览中的功能不受官方 GA 功能支持 SLA 的约束。 以下是如何创建二进制量化索引的示例:

PUT my-byte-quantized-index
{
  "mappings": {
    "properties": {
      "my_vector": {
        "type": "dense_vector",
        "dims": 64,
        "index": true,
        "index_options": {
          "type": "bbq_hnsw"
        }
      }
    }
  }
}

密集向量字段的参数

edit

接受的映射参数如下:

element_type
(可选, 字符串) 用于编码向量的数据类型。支持的数据类型有 float(默认)、byte 和 bit。
有效的element_type
float
为每个维度索引一个4字节的浮点值。这是默认值。
byte
为每个维度索引一个1字节整数值。
bit
为每个维度索引一个单独的位。适用于非常高维的向量或特别支持位向量的模型。 注意:当使用bit时,维度的数量必须是8的倍数,并且必须表示位数。
dims
(可选,整数) 向量的维度数量。不能超过4096。如果未指定dims,则将设置为添加到该字段中的第一个向量的长度。
index
(可选, 布尔值) 如果为true,您可以使用kNN搜索API来搜索此字段。默认为true
similarity
(可选*, 字符串) 用于kNN搜索的向量相似度度量。文档根据其向量字段与查询向量的相似度进行排序。每个文档的_score将根据相似度得出,以确保分数为正且分数越大表示排名越高。 当element_type: bit时,默认值为l2_norm,否则默认值为cosine

bit 向量仅支持 l2_norm 作为它们的相似度度量。

+ *indextrue 时,才能指定此参数。

+ . similarity 的有效值

详情
l2_norm
基于向量之间的L2距离(也称为欧几里得距离)计算相似度。文档的_score计算公式为 1 / (1 + l2_norm(query, vector)^2)

对于bit向量,不使用l2_norm,而是使用向量之间的hamming距离。_score 的转换公式为(numBits - hamming(a, b)) / numBits

dot_product

计算两个单位向量的点积。此选项提供了一种优化的方式来执行余弦相似度。约束条件和计算的分数由element_type定义。

element_typefloat 时,所有向量必须为单位长度,包括文档和查询向量。文档的 _score 计算公式为 (1 + dot_product(query, vector)) / 2

element_typebyte 时,所有向量必须具有相同的长度,包括文档向量和查询向量,否则结果将不准确。 文档的 _score 计算公式为 0.5 + (dot_product(query, vector) / (32768 * dims)) 其中 dims 是每个向量的维度数。

cosine
计算余弦相似度。在索引期间,Elasticsearch 会自动将使用 cosine 相似度的向量归一化为单位长度。这使得内部可以使用 dot_product 来计算相似度,从而提高效率。原始的未归一化向量仍然可以通过脚本访问。文档的 _score 计算为 (1 + cosine(query, vector)) / 2cosine 相似度不允许零幅值的向量,因为在这种情况下余弦未定义。
max_inner_product
计算两个向量的最大内积。这类似于dot_product,但不要求向量归一化。这意味着每个向量的幅度可以显著影响分数。文档的_score被调整以防止负值。对于max_inner_product< 0_score1 / (1 + -1 * max_inner_product(query, vector))。对于非负的max_inner_product结果,_score计算为max_inner_product(query, vector) + 1

尽管它们在概念上相关,但similarity参数与text字段的similarity不同,并接受一组不同的选项。

index_options

(可选*,对象) 一个可选的部分,用于配置kNN索引算法。HNSW算法有两个内部参数,影响数据结构的构建方式。可以调整这些参数以提高结果的准确性,但会牺牲索引速度。

*indextrue时,才能指定此参数。

Properties of index_options
type

(必需,字符串) 要使用的kNN算法的类型。可以是以下任意一种:

  • hnsw - 这利用了HNSW算法进行可扩展的近似kNN搜索。这支持所有element_type值。
  • int8_hnsw - 浮点向量的默认索引类型。 这利用了HNSW算法,并自动进行标量量化,以实现可扩展的近似kNN搜索,element_typefloat。这可以减少4倍的内存占用,但会牺牲一些准确性。参见自动量化向量以进行kNN搜索
  • int4_hnsw - 这利用了HNSW算法,并自动进行标量量化,以实现可扩展的近似kNN搜索,element_typefloat。这可以减少8倍的内存占用,但会牺牲一些准确性。参见自动量化向量以进行kNN搜索
  • [preview] 此功能处于技术预览阶段,可能会在未来的版本中更改或删除。Elastic将努力修复任何问题,但技术预览版中的功能不受官方GA功能的SLA支持。 bbq_hnsw - 这利用了HNSW算法,并自动进行二进制量化,以实现可扩展的近似kNN搜索,element_typefloat。这可以减少32倍的内存占用,但会牺牲准确性。参见自动量化向量以进行kNN搜索
  • flat - 这利用了暴力搜索算法进行精确的kNN搜索。这支持所有element_type值。
  • int8_flat - 这利用了暴力搜索算法,并自动进行标量量化。仅支持element_typefloat
  • int4_flat - 这利用了暴力搜索算法,并自动进行半字节标量量化。仅支持element_typefloat
  • [preview] 此功能处于技术预览阶段,可能会在未来的版本中更改或删除。Elastic将努力修复任何问题,但技术预览版中的功能不受官方GA功能的SLA支持。 bbq_flat - 这利用了暴力搜索算法,并自动进行二进制量化。仅支持element_typefloat
m
(可选,整数) HNSW图中每个节点将连接的邻居数量。 默认为16。仅适用于hnswint8_hnswint4_hnsw索引类型。
ef_construction
(可选,整数) 在为每个新节点组装最近邻居列表时跟踪的候选者数量。默认为100。仅适用于hnswint8_hnswint4_hnsw索引类型。
confidence_interval
(可选,浮点数) 仅适用于int8_hnswint4_hnswint8_flatint4_flat索引类型。量化向量时使用的置信区间。 可以是0.901.0之间的任何值,包括0.901.0,或正好是0。当值为0时,表示应为优化量化计算动态分位数。当值在0.901.0之间时,此值限制了计算量化阈值时使用的值。 例如,值为0.95时,仅使用中间95%的值来计算量化阈值(例如,最高和最低2.5%的值将被忽略)。 默认为int8量化向量的1/(dims + 1)int40用于动态分位数计算。

合成 _source

edit

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

dense_vector 字段支持 合成 _source

索引与搜索位向量

edit

当使用element_type: bit时,这将把所有向量视为位向量。位向量每个维度仅使用一个位,并在内部编码为字节。这对于非常高维的向量或模型非常有用。

当使用bit时,维度的数量必须是8的倍数,并且必须表示位数。此外,使用bit向量时,典型的向量相似性值实际上都被评分相同,例如使用hamming距离。

让我们比较两个 byte[] 数组,每个数组代表40个单独的位。

[-127, 0, 1, 42, 127] 以位表示为 1000000100000000000000010010101001111111 [127, -127, 0, 1, 42] 以位表示为 0111111110000001000000000000000100101010

在比较这两个位向量时,我们首先计算汉明距离

xor 结果:

1000000100000000000000010010101001111111
^
0111111110000001000000000000000100101010
=
1111111010000001000000010010101101010101

然后,我们计算xor结果中1位的数量:18。为了进行评分缩放,我们从总位数中减去并除以总位数:(40 - 18) / 40 = 0.55。这将是这两个向量之间的_score

这是一个关于位向量索引和搜索的示例:

PUT my-bit-vectors
{
  "mappings": {
    "properties": {
      "my_vector": {
        "type": "dense_vector",
        "dims": 40, 
        "element_type": "bit"
      }
    }
  }
}

表示位数的维度数量

POST /my-bit-vectors/_bulk?refresh
{"index": {"_id" : "1"}}
{"my_vector": [127, -127, 0, 1, 42]} 
{"index": {"_id" : "2"}}
{"my_vector": "8100012a7f"} 

表示40位维度向量的5个字节

一个表示40位维度向量的十六进制字符串

然后,在搜索时,您可以使用 knn 查询来搜索相似的位向量:

POST /my-bit-vectors/_search?filter_path=hits.hits
{
  "query": {
    "knn": {
      "query_vector": [127, -127, 0, 1, 42],
      "field": "my_vector"
    }
  }
}
{
    "hits": {
        "hits": [
            {
                "_index": "my-bit-vectors",
                "_id": "1",
                "_score": 1.0,
                "_source": {
                    "my_vector": [
                        127,
                        -127,
                        0,
                        1,
                        42
                    ]
                }
            },
            {
                "_index": "my-bit-vectors",
                "_id": "2",
                "_score": 0.55,
                "_source": {
                    "my_vector": "8100012a7f"
                }
            }
        ]
    }
}

可更新的字段类型

edit

为了更好地适应扩展和性能需求,可以使用更新映射API来更新index_options中的type设置,如下图所示(允许跳跃):

flat --> int8_flat --> int4_flat --> hnsw --> int8_hnsw --> int4_hnsw

对于更新所有HNSW类型(hnswint8_hnswint4_hnsw),连接数m必须保持不变或增加。对于标量量化格式(int8_flatint4_flatint8_hnswint4_hnsw),confidence_interval必须始终保持一致(一旦定义,不能更改)。

在所有其他情况下,更新 index_options 中的 type 将会失败。

切换类型不会重新索引已经索引的向量(它们将继续使用其原始类型),更改后索引的向量将使用新的类型

例如,可以定义一个密集向量字段,该字段利用flat类型(原始float32数组)来索引第一批数据。

PUT my-index-000001
{
    "mappings": {
        "properties": {
            "text_embedding": {
                "type": "dense_vector",
                "dims": 384,
                "index_options": {
                    "type": "flat"
                }
            }
        }
    }
}

type更改为int4_hnsw可以确保更改后索引的向量将使用int4标量量化表示和HNSW(例如,用于KNN查询)。 这包括由合并先前创建的段而创建的新段。

PUT /my-index-000001/_mapping
{
    "properties": {
        "text_embedding": {
            "type": "dense_vector",
            "dims": 384,
            "index_options": {
                "type": "int4_hnsw"
            }
        }
    }
}

在此更改之前索引的向量将继续使用flat类型(原始float32表示和用于KNN查询的暴力搜索)。

为了将所有向量更新为新类型,应使用重新索引或强制合并。

为了调试目的,可以使用索引段API检查每个类型存在多少个段(和文档)。

展平字段类型

edit

默认情况下,对象中的每个子字段都会分别进行映射和索引。如果子字段的名称或类型不是预先知道的,那么它们会动态映射

The flattened 类型提供了一种替代方法,其中整个对象被映射为一个单一字段。给定一个对象,flattened 映射将解析其叶子值,并将它们作为关键字索引到一个字段中。然后可以通过简单的查询和聚合来搜索对象的内容。

这种数据类型对于索引具有大量或未知数量唯一键的对象非常有用。整个JSON对象只创建一个字段映射,这有助于防止因过多不同字段映射而导致的映射爆炸

另一方面,扁平化的对象字段在搜索功能方面存在一定的权衡。仅允许基本查询,不支持数值范围查询或高亮显示。有关限制的更多信息,请参阅支持的操作部分。

不应使用 flattened 映射类型来索引所有文档内容,因为它将所有值视为关键词,并且不提供完整的搜索功能。默认方法,即每个子字段在映射中都有自己的条目,在大多数情况下都能很好地工作。

可以按如下方式创建一个扁平化的对象字段:

PUT bug_reports
{
  "mappings": {
    "properties": {
      "title": {
        "type": "text"
      },
      "labels": {
        "type": "flattened"
      }
    }
  }
}

POST bug_reports/_doc/1
{
  "title": "Results are not sorted correctly.",
  "labels": {
    "priority": "urgent",
    "release": ["v1.2.5", "v1.3.0"],
    "timestamp": {
      "created": 1541458026,
      "closed": 1541457010
    }
  }
}

在索引过程中,会为JSON对象中的每个叶子值创建标记。这些值被索引为字符串关键字,不进行分析或对数字或日期进行特殊处理。

查询顶层的 flattened 字段会搜索对象中的所有叶子值:

POST bug_reports/_search
{
  "query": {
    "term": {"labels": "urgent"}
  }
}

要在扁平化对象中查询特定键,使用对象点表示法:

POST bug_reports/_search
{
  "query": {
    "term": {"labels.release": "v1.3.0"}
  }
}

支持的操作

edit

由于值的索引方式相似,flattened 字段与 keyword 字段在映射和搜索功能上有很多相似之处。

目前,扁平化对象字段可以用于以下查询类型:

  • term, terms, 和 terms_set
  • prefix
  • range
  • matchmulti_match
  • query_stringsimple_query_string
  • exists

在查询时,无法使用通配符引用字段键,例如 { "term": {"labels.time*": 1541457010}}。请注意,所有查询,包括 range,都将值视为字符串关键字。在 flattened 字段上不支持高亮显示。

可以对展平的对象字段进行排序,并执行简单的关键字风格聚合,例如 terms。与查询一样,没有对数值的特殊支持——JSON 对象中的所有值都被视为关键字。在排序时,这意味着值是按字典顺序进行比较的。

目前无法存储扁平化的对象字段。无法在映射中指定store参数。

检索扁平化字段

edit

可以使用fields参数检索字段值和具体子字段。由于flattened字段将整个对象映射为单个字段,因此响应包含来自_source的未修改结构。

然而,单个子字段可以通过在请求中明确指定它们来获取。 这仅适用于具体路径,但不能使用通配符:

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "flattened_field": {
        "type": "flattened"
      }
    }
  }
}

PUT my-index-000001/_doc/1?refresh=true
{
  "flattened_field" : {
    "subfield" : "value"
  }
}

POST my-index-000001/_search
{
  "fields": ["flattened_field.subfield"],
  "_source": false
}
{
  "took": 2,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 1.0,
    "hits": [{
      "_index": "my-index-000001",
      "_id": "1",
      "_score": 1.0,
      "fields": {
        "flattened_field.subfield" : [ "value" ]
      }
    }]
  }
}

您还可以使用Painless脚本从扁平化字段的子字段中检索值。在您的Painless脚本中,使用doc['.'].value而不是doc[''].value。例如,如果您有一个名为label的扁平化字段,并且它有一个release子字段,您的Painless脚本将是doc['labels.release'].value

例如,假设您的映射包含两个字段,其中一个字段的类型是flattened

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "title": {
        "type": "text"
      },
      "labels": {
        "type": "flattened"
      }
    }
  }
}

索引一些包含映射字段的文档。labels 字段有三个子字段:

POST /my-index-000001/_bulk?refresh
{"index":{}}
{"title":"Something really urgent","labels":{"priority":"urgent","release":["v1.2.5","v1.3.0"],"timestamp":{"created":1541458026,"closed":1541457010}}}
{"index":{}}
{"title":"Somewhat less urgent","labels":{"priority":"high","release":["v1.3.0"],"timestamp":{"created":1541458026,"closed":1541457010}}}
{"index":{}}
{"title":"Not urgent","labels":{"priority":"low","release":["v1.2.0"],"timestamp":{"created":1541458026,"closed":1541457010}}}

因为 labels 是一个 flattened 字段类型,整个对象被映射为一个单一字段。要在 Painless 脚本中从这个子字段中检索值,请使用 doc['.'].value 格式。

"script": {
  "source": """
    if (doc['labels.release'].value.equals('v1.3.0'))
    {emit(doc['labels.release'].value)}
    else{emit('Version mismatch')}
  """

扁平化对象字段的参数

edit

接受的映射参数如下:

depth_limit

展平对象字段允许的最大深度,以嵌套内部对象的形式表示。如果展平对象字段超过此限制,则会抛出错误。默认值为20。请注意,depth_limit可以通过更新映射 API动态更新。

doc_values

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

eager_global_ordinals

是否应在刷新时急切加载全局序数?接受 truefalse(默认)。在频繁用于词条聚合的字段上启用此功能是一个好主意。

ignore_above

超过此限制的叶子值将不会被索引。默认情况下,没有限制,所有值都会被索引。请注意,此限制适用于扁平化对象字段中的叶子值,而不是整个字段的长度。

index

确定字段是否应可搜索。接受 true(默认)或 false

index_options

在评分目的中,索引中应存储哪些信息。默认值为 docs,但也可以设置为 freqs,以便在计算分数时考虑词频。

null_value

一个字符串值,用于替换扁平化对象字段中任何显式的 null 值。默认为 null,这意味着 null 字段被视为缺失。

similarity

使用哪种评分算法或相似度。默认为BM25

split_queries_on_whitespace

是否应在为此字段构建查询时,将全文查询的输入在空白处拆分。接受truefalse(默认)。

时间序列维度

(可选,字符串数组) 扁平化对象内的字段列表,其中每个字段是时间序列的一个维度。每个字段使用从根字段开始的相对路径指定,并且不包括根字段名称。

合成 _source

edit

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

扁平化字段在其默认配置中支持合成 `_source`

合成源可能会对扁平化字段值进行排序并去除重复项。 例如:

PUT idx
{
  "settings": {
    "index": {
      "mapping": {
        "source": {
          "mode": "synthetic"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "flattened": { "type": "flattened" }
    }
  }
}
PUT idx/_doc/1
{
  "flattened": {
    "field": [ "apple", "apple", "banana", "avocado", "10", "200", "AVOCADO", "Banana", "Tangerine" ]
  }
}

将变为:

{
  "flattened": {
    "field": [ "10", "200", "AVOCADO", "Banana", "Tangerine", "apple", "avocado", "banana" ]
  }
}

合成源始终使用嵌套对象而不是对象数组。 例如:

PUT idx
{
  "settings": {
    "index": {
      "mapping": {
        "source": {
          "mode": "synthetic"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "flattened": { "type": "flattened" }
    }
  }
}
PUT idx/_doc/1
{
  "flattened": {
      "field": [
        { "id": 1, "name": "foo" },
        { "id": 2, "name": "bar" },
        { "id": 3, "name": "baz" }
      ]
  }
}

将变为(注意嵌套对象而不是“扁平化”数组):

{
    "flattened": {
      "field": {
          "id": [ "1", "2", "3" ],
          "name": [ "bar", "baz", "foo" ]
      }
    }
}

合成源始终对单元素数组使用单值字段。 例如:

PUT idx
{
  "settings": {
    "index": {
      "mapping": {
        "source": {
          "mode": "synthetic"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "flattened": { "type": "flattened" }
    }
  }
}
PUT idx/_doc/1
{
  "flattened": {
    "field": [ "foo" ]
  }
}

将变为(注意嵌套对象而不是“扁平化”数组):

{
  "flattened": {
    "field": "foo"
  }
}

地理点字段类型

edit

类型为 geo_point 的字段接受纬度-经度对,这些可以用于:

geo_shapepoint一样,geo_point可以在GeoJSONWell-Known Text格式中指定。 然而,出于方便和历史原因,还支持许多其他格式。 总共有六种方式可以指定一个地理点,如下所示:

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "location": {
        "type": "geo_point"
      }
    }
  }
}

PUT my-index-000001/_doc/1
{
  "text": "Geopoint as an object using GeoJSON format",
  "location": { 
    "type": "Point",
    "coordinates": [-71.34, 41.12]
  }
}

PUT my-index-000001/_doc/2
{
  "text": "Geopoint as a WKT POINT primitive",
  "location" : "POINT (-71.34 41.12)" 
}

PUT my-index-000001/_doc/3
{
  "text": "Geopoint as an object with 'lat' and 'lon' keys",
  "location": { 
    "lat": 41.12,
    "lon": -71.34
  }
}

PUT my-index-000001/_doc/4
{
  "text": "Geopoint as an array",
  "location": [ -71.34, 41.12 ] 
}

PUT my-index-000001/_doc/5
{
  "text": "Geopoint as a string",
  "location": "41.12,-71.34" 
}

PUT my-index-000001/_doc/6
{
  "text": "Geopoint as a geohash",
  "location": "drm3btev3e86" 
}

GET my-index-000001/_search
{
  "query": {
    "geo_bounding_box": { 
      "location": {
        "top_left": {
          "lat": 42,
          "lon": -72
        },
        "bottom_right": {
          "lat": 40,
          "lon": -74
        }
      }
    }
  }
}

以对象形式表示的地理点,采用GeoJSON格式,包含typecoordinates键。

Well-Known Text表示的地理点 格式为:"POINT(lon lat)"

以对象表示的地理点,包含latlon键。

地理点表示为一个数组,格式为:[ lon, lat]

以字符串形式表示的地理点,格式为:"纬度,经度"

以geohash表示的地理点。

一个地理边界框查询,用于查找所有位于该框内的地理点。

以数组或字符串表示的地理点

请注意,字符串地理点按 纬度,经度 顺序排列,而数组地理点、GeoJSON 和 WKT 则按相反顺序排列:经度,纬度

这一现象的原因是历史性的。地理学家传统上先写纬度,再写经度,而最近为地理数据指定的格式,如GeoJSONWell-Known Text,则先写经度,再写纬度(东距在前,北距在后),以符合数学上先写x再写y的惯例。

一个点可以表示为一个geohash。 Geohash是纬度和经度的位交错后的base32编码字符串。 每个字符在geohash中增加了额外的5位精度。因此,哈希值越长,精度越高。 为了索引目的,geohash被转换为纬度-经度对。在此过程中仅使用前12个字符, 因此指定超过12个字符的geohash不会增加精度。12个字符提供了60位, 这应该将可能的误差减少到小于2厘米。

geo_point 字段的参数

edit

以下参数被geo_point字段接受:

ignore_malformed

如果true,格式错误的geopoints将被忽略。如果false(默认),格式错误的geopoints将抛出异常并拒绝整个文档。 geopoint被认为是格式错误的情况是,其纬度超出范围-90 ⇐ 纬度 ⇐ 90,或者其经度超出范围-180 ⇐ 经度 ⇐ 180。 请注意,如果使用了script参数,则无法设置此项。

ignore_z_value

如果为true(默认),将接受三维点(存储在源中),但仅索引纬度和经度值;忽略第三维度。如果为false,包含超过纬度和经度(二维)值的地理点将抛出异常并拒绝整个文档。请注意,如果使用了script参数,则无法设置此项。

index

字段是否应快速可搜索?接受 true(默认)和 false。仅启用了 doc_values 的字段仍然可以查询,尽管速度较慢。

null_value

接受一个地理点值,该值将替换任何显式的 null 值。默认值为 null,这意味着该字段被视为缺失。请注意,如果使用了 script 参数,则不能设置此项。

on_script_error

定义如果在索引时由script参数定义的脚本抛出错误时应执行的操作。接受fail(默认),这将导致整个文档被拒绝,以及continue,这将把字段注册在文档的_ignored元数据字段中并继续索引。此参数只能在设置了script字段时设置。

脚本

如果设置了此参数,则该字段将索引由此脚本生成的值,而不是直接从源中读取值。如果在输入文档上为此字段设置了值,则文档将被拒绝并返回错误。 脚本格式与其运行时等效相同,并且应发出一对(lat, lon)双精度值。

在脚本中使用地理点

edit

当在脚本中访问地理点的值时,该值将返回为一个GeoPoint对象,从而可以分别访问.lat.lon值:

def geopoint = doc['location'].value;
def lat      = geopoint.lat;
def lon      = geopoint.lon;

出于性能原因,直接访问纬度/经度值会更好:

def lat      = doc['location'].lat;
def lon      = doc['location'].lon;

合成源

edit

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

合成源可能会对geo_point字段进行排序(先按纬度,再按经度),并将它们减少到存储的精度。例如:

PUT idx
{
  "settings": {
    "index": {
      "mapping": {
        "source": {
          "mode": "synthetic"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "point": { "type": "geo_point" }
    }
  }
}
PUT idx/_doc/1
{
  "point": [
    {"lat":-90, "lon":-80},
    {"lat":10, "lon":30}
  ]
}

将变为:

{
  "point": [
    {"lat":-90.0, "lon":-80.00000000931323},
    {"lat":9.999999990686774, "lon":29.999999972060323}
   ]
}

地理形状字段类型

edit

The geo_shape 数据类型有助于索引和搜索任意地理形状,如矩形、线和多边形。如果被索引的数据包含的形状不仅仅是点,则需要使用此映射。如果数据仅包含点,则可以将其索引为 geo_pointgeo_shape

使用此类型的文档可以用于:

映射选项

edit

The geo_shape mapping maps GeoJSON or WKT geometry objects to the geo_shape type. 要启用它,用户必须显式地将字段映射到 geo_shape 类型。

GeoJSONWKT 中,因此也在 Elasticsearch 中, 坐标数组中的正确 坐标顺序是经度, 纬度 (X, Y)。这与许多地理空间 API(例如,Google Maps)通常使用的非正式纬度, 经度 (Y, X) 不同。

Option Description Default

方向

可选。字段的WKT多边形的默认方向

此参数设置并返回仅一个RIGHT(逆时针)或LEFT(顺时针)值。然而,您可以通过多种方式指定任一值。

要设置RIGHT,请使用以下参数之一或其大写变体:

  • 逆时针
  • 逆时针

要设置LEFT,请使用以下参数之一或其大写变体:

  • 顺时针
  • 顺时针

RIGHT

ignore_malformed

如果为真,格式错误的GeoJSON或WKT形状将被忽略。如果为假(默认),格式错误的GeoJSON和WKT形状将抛出异常并拒绝整个文档。

ignore_z_value

如果为true(默认),将接受三维点(存储在源中),但仅索引纬度和经度值;第三维度被忽略。如果为false,则包含超过纬度和经度(二维)值的地理点将抛出异常并拒绝整个文档。

coerce

如果 true,多边形中未闭合的线性环将自动闭合。

索引

字段是否应该快速可搜索?接受 true(默认)和 false。 仅启用了 doc_values 的字段仍然可以查询,尽管速度较慢。

doc_values

字段是否应以列步长的方式存储在磁盘上,以便以后可以用于聚合或脚本编写?

索引方法

edit

Geoshape 类型通过将形状分解为三角网格并 将每个三角形索引为 BKD 树中的一个 7 维点来进行索引。这提供了 接近完美的空间分辨率(精度可达 1e-7 小数度),因为所有 空间关系都是使用原始形状的编码向量表示来计算的。镶嵌器的主要性能 主要取决于定义多边形/多边形的顶点数量。

示例
edit
PUT /example
{
  "mappings": {
    "properties": {
      "location": {
        "type": "geo_shape"
      }
    }
  }
}

输入结构

edit

形状可以使用GeoJSON熟知文本 (WKT)格式表示。下表提供了GeoJSON和WKT到Elasticsearch类型的映射:

GeoJSON Type WKT Type Elasticsearch Type Description

一个地理坐标。注意:Elasticsearch仅使用WGS-84坐标。

LineString

LINESTRING

linestring

给定两个或更多点的一条任意线。

多边形

多边形

多边形

一个闭合的多边形,其第一个和最后一个点必须匹配,因此需要n + 1个顶点来创建一个n边形,并且最少需要4个顶点。

多点

多点

多点

一组未连接但可能相关的点。

多线串

MULTILINESTRING

多线串

一组独立的线串。

多边形集合

MULTIPOLYGON

多边形集合

一个由多个独立多边形组成的数组。

GeometryCollection

GEOMETRYCOLLECTION

几何集合

一个类似于multi*形状的GeoJSON形状,不同之处在于多种类型可以共存(例如,一个点和一个线串)。

N/A

BBOX

信封

一个边界矩形,或信封,通过仅指定左上角和右下角点来指定。

对于所有类型,typecoordinates 字段都是必需的。

点是一个单一的地理坐标,例如建筑物的位置或智能手机的Geolocation API提供的当前位置。以下是GeoJSON中一个点的示例。

POST /example/_doc
{
  "location" : {
    "type" : "Point",
    "coordinates" : [-77.03653, 38.897676]
  }
}

以下是一个WKT中点的示例:

POST /example/_doc
{
  "location" : "POINT (-77.03653 38.897676)"
}

由两个或更多位置组成的数组定义的线串。通过仅指定两个点,线串将表示一条直线。指定两个以上的点将创建任意路径。以下是GeoJSON中线串的一个示例。

POST /example/_doc
{
  "location" : {
    "type" : "LineString",
    "coordinates" : [[-77.03653, 38.897676], [-77.009051, 38.889939]]
  }
}

以下是WKT中一个线串的示例:

POST /example/_doc
{
  "location" : "LINESTRING (-77.03653 38.897676, -77.009051 38.889939)"
}

上述线字符串将从白宫开始绘制一条直线到美国国会大厦。

多边形由一系列点列表定义。每个(外部)列表中的第一个和最后一个点必须是相同的(多边形必须是封闭的)。以下是GeoJSON中多边形的一个示例。

POST /example/_doc
{
  "location" : {
    "type" : "Polygon",
    "coordinates" : [
      [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ]
    ]
  }
}

以下是WKT中多边形的一个示例:

POST /example/_doc
{
  "location" : "POLYGON ((100.0 0.0, 101.0 0.0, 101.0 1.0, 100.0 1.0, 100.0 0.0))"
}

第一个数组表示多边形的外边界,其他数组表示内部形状(“孔”)。以下是一个带有孔的多边形的GeoJSON示例:

POST /example/_doc
{
  "location" : {
    "type" : "Polygon",
    "coordinates" : [
      [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ],
      [ [100.2, 0.2], [100.8, 0.2], [100.8, 0.8], [100.2, 0.8], [100.2, 0.2] ]
    ]
  }
}

以下是一个带有孔洞的多边形的WKT示例:

POST /example/_doc
{
  "location" : "POLYGON ((100.0 0.0, 101.0 0.0, 101.0 1.0, 100.0 1.0, 100.0 0.0), (100.2 0.2, 100.8 0.2, 100.8 0.8, 100.2 0.8, 100.2 0.2))"
}
多边形方向
edit

多边形的方向表示其顶点的顺序:RIGHT(逆时针)或LEFT(顺时针)。Elasticsearch使用多边形的方向来确定它是否跨越国际日期变更线(+/-180°经度)。

您可以使用orientation 映射参数为WKT多边形设置默认方向。这是因为WKT规范没有指定或强制默认方向。

GeoJSON 多边形使用默认的 RIGHT 方向,无论 orientation 映射参数的值如何。这是因为 GeoJSON 规范 规定外多边形使用逆时针方向,而内部形状使用顺时针方向。

您可以使用文档级别的 orientation 参数覆盖GeoJSON多边形的默认方向。例如,以下索引请求指定了一个文档级别的 orientationLEFT

POST /example/_doc
{
  "location" : {
    "type" : "Polygon",
    "orientation" : "LEFT",
    "coordinates" : [
      [ [-177.0, 10.0], [176.0, 15.0], [172.0, 0.0], [176.0, -15.0], [-177.0, -10.0], [-177.0, 10.0] ]
    ]
  }
}

Elasticsearch 仅使用多边形的方向来确定它是否穿越国际日期变更线。如果多边形的最小经度和最大经度之间的差异小于180°,则该多边形不会穿越日期变更线,其方向没有影响。

如果一个多边形的最小经度和最大经度之间的差值为180°或更大,Elasticsearch会检查该多边形的文档级orientation是否与默认方向不同。如果方向不同,Elasticsearch会认为该多边形跨越了国际日期变更线,并在日期变更线处将多边形分割。

以下是GeoJSON点列表的一个示例:

POST /example/_doc
{
  "location" : {
    "type" : "MultiPoint",
    "coordinates" : [
      [102.0, 2.0], [103.0, 2.0]
    ]
  }
}

以下是一个WKT点列表的示例:

POST /example/_doc
{
  "location" : "MULTIPOINT (102.0 2.0, 103.0 2.0)"
}

以下是一个GeoJSON线串列表的示例:

POST /example/_doc
{
  "location" : {
    "type" : "MultiLineString",
    "coordinates" : [
      [ [102.0, 2.0], [103.0, 2.0], [103.0, 3.0], [102.0, 3.0] ],
      [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0] ],
      [ [100.2, 0.2], [100.8, 0.2], [100.8, 0.8], [100.2, 0.8] ]
    ]
  }
}

以下是WKT线串列表的一个示例:

POST /example/_doc
{
  "location" : "MULTILINESTRING ((102.0 2.0, 103.0 2.0, 103.0 3.0, 102.0 3.0), (100.0 0.0, 101.0 0.0, 101.0 1.0, 100.0 1.0), (100.2 0.2, 100.8 0.2, 100.8 0.8, 100.2 0.8))"
}

以下是一个包含GeoJSON多边形列表的示例(第二个多边形包含一个洞):

POST /example/_doc
{
  "location" : {
    "type" : "MultiPolygon",
    "coordinates" : [
      [ [[102.0, 2.0], [103.0, 2.0], [103.0, 3.0], [102.0, 3.0], [102.0, 2.0]] ],
      [ [[100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0]],
        [[100.2, 0.2], [100.8, 0.2], [100.8, 0.8], [100.2, 0.8], [100.2, 0.2]] ]
    ]
  }
}

以下是一个WKT多边形列表的示例(第二个多边形包含一个洞):

POST /example/_doc
{
  "location" : "MULTIPOLYGON (((102.0 2.0, 103.0 2.0, 103.0 3.0, 102.0 3.0, 102.0 2.0)), ((100.0 0.0, 101.0 0.0, 101.0 1.0, 100.0 1.0, 100.0 0.0), (100.2 0.2, 100.8 0.2, 100.8 0.8, 100.2 0.8, 100.2 0.2)))"
}

以下是一个包含多个GeoJSON几何对象的示例:

POST /example/_doc
{
  "location" : {
    "type": "GeometryCollection",
    "geometries": [
      {
        "type": "Point",
        "coordinates": [100.0, 0.0]
      },
      {
        "type": "LineString",
        "coordinates": [ [101.0, 0.0], [102.0, 1.0] ]
      }
    ]
  }
}

以下是一个WKT几何对象集合的示例:

POST /example/_doc
{
  "location" : "GEOMETRYCOLLECTION (POINT (100.0 0.0), LINESTRING (101.0 0.0, 102.0 1.0))"
}
信封
edit

Elasticsearch 支持一种 envelope 类型,它由形状的左上角和右下角的坐标组成,以表示边界矩形,格式为 [[minLon, maxLat], [maxLon, minLat]]

POST /example/_doc
{
  "location" : {
    "type" : "envelope",
    "coordinates" : [ [100.0, 1.0], [101.0, 0.0] ]
  }
}

以下是使用WKT BBOX格式的信封示例:

注意: WKT 规范要求以下顺序:minLon, maxLon, maxLat, minLat。

POST /example/_doc
{
  "location" : "BBOX (100.0, 102.0, 2.0, 0.0)"
}
圆形
edit

GeoJSON 和 WKT 都不支持点-半径圆类型。相反,使用圆摄取处理器将圆近似为多边形

排序和检索索引形状

edit

由于形状的复杂输入结构和索引表示,目前无法直接对形状进行排序或检索其字段。geo_shape 值只能通过 _source 字段检索。

合成源

edit

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

直方图字段类型

edit

用于存储表示直方图的预聚合数值数据的字段。 此数据使用两个配对数组定义:

  • 一个values数组,包含double类型的数字,表示直方图的桶。这些值必须按升序排列。
  • 一个相应的counts数组,包含long类型的数字,表示每个桶中有多少值。这些数字必须是正数或零。

因为values数组中的元素与count数组中相同位置的元素相对应,所以这两个数组必须具有相同的长度。

  • 一个直方图字段每个文档只能存储一对计数数组。不支持嵌套数组。
  • 直方图字段不支持排序。

用途

edit

histogram 字段主要用于聚合。为了使其更易于用于聚合,histogram 字段数据存储为二进制 doc values 而不是索引。其大小(以字节为单位)最多为 13 * numValues,其中 numValues 是提供的数组的长度。

由于数据未被索引,您只能将 histogram 字段用于以下聚合和查询:

构建直方图

edit

在使用直方图作为聚合的一部分时,结果的准确性将取决于直方图的构建方式。考虑用于构建直方图的分位数聚合模式非常重要。一些可能性包括:

  • 对于T-Digest模式,values数组表示平均质心位置,而counts数组表示归属于每个质心的值的数量。如果算法已经开始近似百分位数,这种不准确性会在直方图中延续。
  • 对于高动态范围 (HDR)直方图模式,values数组表示每个桶区间的固定上限,而counts数组表示归属于每个区间的值的数量。此实现保持固定的最坏情况百分比误差(以有效数字的数量指定),因此在生成直方图时使用的值将是您在聚合时可以实现的最大精度。

直方图字段是“算法无关”的,并且不存储特定于T-Digest或HDRHistogram的数据。虽然这意味着该字段在技术上可以使用任一算法进行聚合,但实际上用户应选择一种算法并以该方式索引数据(例如,T-Digest的质心或HDRHistogram的区间),以确保最佳准确性。

合成 _source

edit

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

直方图 字段支持在其默认配置中使用 合成 _source

为了节省空间,直方图文档值中不存储零计数的桶。因此,当在启用了合成源的索引中索引直方图字段时,索引包含零计数桶的直方图将导致在获取直方图时缺少桶。

示例

edit

以下创建索引 API 请求创建了一个包含两个字段映射的新索引:

  • my_histogram,一个用于存储百分位数据的histogram字段
  • my_text,一个用于存储直方图标题的keyword字段
PUT my-index-000001
{
  "mappings" : {
    "properties" : {
      "my_histogram" : {
        "type" : "histogram"
      },
      "my_text" : {
        "type" : "keyword"
      }
    }
  }
}

以下索引 API 请求存储了两个直方图的预聚合数据:histogram_1histogram_2

PUT my-index-000001/_doc/1
{
  "my_text" : "histogram_1",
  "my_histogram" : {
      "values" : [0.1, 0.2, 0.3, 0.4, 0.5], 
      "counts" : [3, 7, 23, 12, 6] 
   }
}

PUT my-index-000001/_doc/2
{
  "my_text" : "histogram_2",
  "my_histogram" : {
      "values" : [0.1, 0.25, 0.35, 0.4, 0.45, 0.5], 
      "counts" : [8, 17, 8, 7, 6, 2] 
   }
}

每个桶的值。数组中的值被视为双精度数,并且必须按递增顺序给出。对于T-Digest直方图,此值表示平均值。在HDR直方图的情况下,这表示迭代到的值。

每个桶的计数。数组中的值被视为长整数,并且必须为正数或零。负值将被拒绝。桶与计数之间的关系由数组中的位置给出。

IP 字段类型

edit

一个ip字段可以索引/存储IPv4IPv6地址。

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "ip_addr": {
        "type": "ip"
      }
    }
  }
}

PUT my-index-000001/_doc/1
{
  "ip_addr": "192.168.1.1"
}

GET my-index-000001/_search
{
  "query": {
    "term": {
      "ip_addr": "192.168.0.0/16"
    }
  }
}

您还可以使用 ip_range 数据类型 在单个字段中存储 IP 范围。

ip 字段的参数

edit

以下参数由 ip 字段接受:

doc_values
字段是否应以列步长方式存储在磁盘上,以便以后可以用于排序、聚合或脚本编写?接受 true(默认)或 false
ignore_malformed
如果true,格式错误的IP地址将被忽略。如果false(默认),格式错误的IP地址将抛出异常并拒绝整个文档。请注意,如果使用了script参数,则无法设置此项。
index
字段是否应快速可搜索?接受true(默认)和 false。仅启用了doc_values 的字段仍然可以使用术语或基于范围的查询进行查询, 尽管速度较慢。
null_value
接受一个IPv4或IPv6值,该值将替换任何显式的null值。 默认为null,这意味着该字段被视为缺失。请注意,如果使用了script参数,则不能设置此项。
on_script_error
定义如果在索引时由script参数定义的脚本抛出错误时该怎么办。接受reject(默认),这将导致整个文档被拒绝,以及ignore,这将把字段注册在文档的 _ignored元数据字段中并继续索引。此参数只能在设置了script字段时设置。
script
如果设置此参数,则该字段将索引由此脚本生成的值,而不是直接从源中读取值。如果在输入文档中为此字段设置了值,则文档将被拒绝并返回错误。 脚本格式与其运行时等效相同,并且应发出包含IPv4或IPv6格式地址的字符串。
store
字段值是否应与_source字段分开存储和检索。接受truefalse(默认)。
time_series_dimension

(可选,布尔值)

将字段标记为时间序列维度。默认为false

索引设置 index.mapping.dimension_fields.limit 限制了索引中的维度数量。

维度字段具有以下约束:

  • doc_valuesindex 映射参数必须为 true

查询 ip 字段

edit

查询 IP 地址最常见的方式是使用 CIDR 表示法:[ip_address]/[prefix_length]。例如:

GET my-index-000001/_search
{
  "query": {
    "term": {
      "ip_addr": "192.168.0.0/16"
    }
  }
}

GET my-index-000001/_search
{
  "query": {
    "term": {
      "ip_addr": "2001:db8::/48"
    }
  }
}

还要注意,冒号是query_string查询中的特殊字符,因此ipv6地址将需要进行转义。最简单的方法是在搜索值周围加上引号:

GET my-index-000001/_search
{
  "query": {
    "query_string" : {
      "query": "ip_addr:\"2001:db8::/48\""
    }
  }
}

合成 _source

edit

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

合成源可能会对 ip 字段值进行排序并删除重复项。例如:

PUT idx
{
  "settings": {
    "index": {
      "mapping": {
        "source": {
          "mode": "synthetic"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "ip": { "type": "ip" }
    }
  }
}
PUT idx/_doc/1
{
  "ip": ["192.168.0.1", "192.168.0.1", "10.10.12.123",
         "2001:db8::1:0:0:1", "::afff:4567:890a"]
}

将变为:

{
  "ip": ["::afff:4567:890a", "10.10.12.123", "192.168.0.1", "2001:db8::1:0:0:1"]
}

IPv4 地址按照它们被视为以 ::ffff:0:0:0/96 为前缀的 IPv6 地址进行排序,如 rfc6144 所指定。

连接字段类型

edit

The join 数据类型是一种特殊字段,用于在同一索引的文档中创建父子关系。 The relations 部分定义了文档中可能存在的一组关系, 每个关系由一个父名称和一个子名称组成。

我们不建议使用多级关系来复制关系模型。每一级关系在查询时都会增加内存和计算的开销。为了获得更好的搜索性能,请对数据进行反规范化处理。

父子关系可以定义如下:

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "my_id": {
        "type": "keyword"
      },
      "my_join_field": { 
        "type": "join",
        "relations": {
          "question": "answer" 
        }
      }
    }
  }
}

字段的名称

定义一个单一关系,其中questionanswer的父级。

要使用连接索引文档,必须在source中提供关系名称和可选的文档父级。例如,以下示例在question上下文中创建两个parent文档:

PUT my-index-000001/_doc/1?refresh
{
  "my_id": "1",
  "text": "This is a question",
  "my_join_field": {
    "name": "question" 
  }
}

PUT my-index-000001/_doc/2?refresh
{
  "my_id": "2",
  "text": "This is another question",
  "my_join_field": {
    "name": "question"
  }
}

本文档是一个问题文档。

在索引父文档时,您可以选择仅指定关系的名称作为快捷方式,而不是将其封装在正常的对象表示法中:

PUT my-index-000001/_doc/1?refresh
{
  "my_id": "1",
  "text": "This is a question",
  "my_join_field": "question" 
}

PUT my-index-000001/_doc/2?refresh
{
  "my_id": "2",
  "text": "This is another question",
  "my_join_field": "question"
}

父文档的简单表示法仅使用关系名称。

在索引子文档时,关系的名称以及文档的父ID必须添加到_source中。

需要在同一个分片中索引父文档的血统,因此必须始终使用其更大的父ID来路由子文档。

例如,以下示例展示了如何索引两个文档:

PUT my-index-000001/_doc/3?routing=1&refresh 
{
  "my_id": "3",
  "text": "This is an answer",
  "my_join_field": {
    "name": "answer", 
    "parent": "1" 
  }
}

PUT my-index-000001/_doc/4?routing=1&refresh
{
  "my_id": "4",
  "text": "This is another answer",
  "my_join_field": {
    "name": "answer",
    "parent": "1"
  }
}

路由值是强制性的,因为父文档和子文档必须索引在同一个分片上

answer 是此文档的连接名称

这个子文档的父ID

父连接与性能

edit

join 字段不应该像关系数据库中的连接那样使用。在 Elasticsearch 中,良好性能的关键是将数据反规范化到文档中。每个 join 字段,has_childhas_parent 查询都会对查询性能增加显著的开销。它还可能触发 全局序数 的构建。

唯一一个连接字段有意义的情况是,如果你的数据包含一对多的关系,其中一个实体的数量远远超过另一个实体。这种情况的一个例子是产品及其报价的使用场景。如果报价的数量远远超过产品的数量,那么将产品建模为父文档,将报价建模为子文档是有意义的。

父连接限制

edit
  • 每个索引只允许一个join字段映射。
  • 父文档和子文档必须索引在同一个分片上。 这意味着在获取删除更新子文档时,需要提供相同的routing值。
  • 一个元素可以有多个子元素,但只能有一个父元素。
  • 可以向现有的join字段添加新的关系。
  • 也可以向现有元素添加子元素,但前提是该元素已经是父元素。

使用父连接进行搜索

edit

父连接创建一个字段来索引文档中关系的名称(my_parentmy_child,…​)。

它还为每个父子关系创建一个字段。 这个字段的名字是join字段的名字,后面跟着#和关系中父节点的名字。 因此,例如对于my_parent → [my_child, another_child]关系, join字段会创建一个名为my_join_field#my_parent的附加字段。

此字段包含文档链接到的父级 _id,如果文档是子文档(my_childanother_child),以及文档的 _id,如果它是父文档(my_parent)。

当搜索包含 join 字段的索引时,这两个字段总是会在搜索响应中返回:

GET my-index-000001/_search
{
  "query": {
    "match_all": {}
  },
  "sort": ["my_id"]
}

将返回:

{
  ...,
  "hits": {
    "total": {
      "value": 4,
      "relation": "eq"
    },
    "max_score": null,
    "hits": [
      {
        "_index": "my-index-000001",
        "_id": "1",
        "_score": null,
        "_source": {
          "my_id": "1",
          "text": "This is a question",
          "my_join_field": "question"         
        },
        "sort": [
          "1"
        ]
      },
      {
        "_index": "my-index-000001",
        "_id": "2",
        "_score": null,
        "_source": {
          "my_id": "2",
          "text": "This is another question",
          "my_join_field": "question"          
        },
        "sort": [
          "2"
        ]
      },
      {
        "_index": "my-index-000001",
        "_id": "3",
        "_score": null,
        "_routing": "1",
        "_source": {
          "my_id": "3",
          "text": "This is an answer",
          "my_join_field": {
            "name": "answer",                 
            "parent": "1"                     
          }
        },
        "sort": [
          "3"
        ]
      },
      {
        "_index": "my-index-000001",
        "_id": "4",
        "_score": null,
        "_routing": "1",
        "_source": {
          "my_id": "4",
          "text": "This is another answer",
          "my_join_field": {
            "name": "answer",
            "parent": "1"
          }
        },
        "sort": [
          "4"
        ]
      }
    ]
  }
}

本文档属于 question 连接

本文档属于 question 连接

本文档属于 answer 连接

子文档的链接父ID

父子连接查询和聚合

edit

参见 has_childhas_parent 查询, children 聚合, 以及 inner hits 了解更多信息。

在聚合和脚本中可以访问join字段的值,并且可以使用parent_id查询进行查询:

GET my-index-000001/_search
{
  "query": {
    "parent_id": { 
      "type": "answer",
      "id": "1"
    }
  },
  "aggs": {
    "parents": {
      "terms": {
        "field": "my_join_field#question", 
        "size": 10
      }
    }
  },
  "runtime_mappings": {
    "parent": {
      "type": "long",
      "script": """
        emit(Integer.parseInt(doc['my_join_field#question'].value)) 
      """
    }
  },
  "fields": [
    { "field": "parent" }
  ]
}

查询 parent id 字段(另请参阅 has_parent 查询has_child 查询

父ID字段上进行聚合(另请参阅聚合)

在脚本中访问父ID字段。

全局序数

edit

The join field uses 全局序数 to speed up joins. 全局序数需要在分片发生任何更改后重建。存储在分片中的父ID值越多,重建join字段的全局序数所需的时间就越长。

全局序号默认情况下是即时构建的:如果索引发生了变化, join 字段的全局序号将在刷新过程中重建。 这可能会显著增加刷新的时间。然而,大多数情况下这是正确的权衡,否则全局序号将在第一次使用父-子查询或聚合时重建。 这可能会为您的用户引入显著的延迟峰值,通常情况下这会更糟糕,因为当发生大量写入时,可能会在单个刷新间隔内尝试重建多个 join 字段的全局序号。

join 字段不常使用而写操作频繁时,禁用预加载可能是有意义的:

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "my_join_field": {
        "type": "join",
        "relations": {
           "question": "answer"
        },
        "eager_global_ordinals": false
      }
    }
  }
}

全局序数使用的堆内存量可以按父关系如下检查:

# Per-index
GET _stats/fielddata?human&fields=my_join_field#question

# Per-node per-index
GET _nodes/stats/indices/fielddata?human&fields=my_join_field#question

每个父项的多个子项

edit

也可以为单个父节点定义多个子节点:

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "my_join_field": {
        "type": "join",
        "relations": {
          "question": ["answer", "comment"]  
        }
      }
    }
  }
}

questionanswercomment 的父级。

多级父连接

edit

我们不建议使用多级关系来复制关系模型。每一级关系在查询时都会增加内存和计算的开销。为了获得更好的搜索性能,请对数据进行反规范化处理。

多级父子关系:

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "my_join_field": {
        "type": "join",
        "relations": {
          "question": ["answer", "comment"],  
          "answer": "vote" 
        }
      }
    }
  }
}

questionanswercomment 的父级

answervote 的父级

上面的映射表示以下树:

   question
    /    \
   /      \
comment  answer
           |
           |
          vote

索引一个孙文档需要一个路由值等于祖父(血统中的更大父级):

PUT my-index-000001/_doc/3?routing=1&refresh 
{
  "text": "This is a vote",
  "my_join_field": {
    "name": "vote",
    "parent": "2" 
  }
}

这个子文档必须与其祖父文档和父文档位于同一个分片上

此文档的父ID(必须指向一个answer文档)

关键词类型家族

edit

关键词系列包括以下字段类型:

  • keyword,用于结构化内容,如ID、电子邮件地址、主机名、状态代码、邮政编码或标签。
  • constant_keyword 用于始终包含相同值的关键字字段。
  • wildcard 用于非结构化的机器生成内容。 wildcard 类型针对具有大值或高基数的字段进行了优化。

关键字字段通常用于排序聚合词项级别查询,例如term

避免使用关键词字段进行全文搜索。请改用text字段类型。

关键词字段类型

edit

下面是一个基本keyword字段映射的示例:

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "tags": {
        "type":  "keyword"
      }
    }
  }
}

映射数字标识符

并非所有数值数据都应映射为数值字段数据类型。 Elasticsearch 优化了数值字段,例如 integerlong,用于 range 查询。然而,keyword 字段 更适合 term 和其他 词项级别查询。

标识符,如ISBN或产品ID,很少用于范围查询。然而,它们通常使用术语级查询来检索。

如果满足以下条件,请考虑将数值标识符映射为keyword

  • 您不打算使用range查询来搜索标识符数据。
  • 快速检索很重要。term查询在keyword字段上的搜索通常比在数值字段上的term搜索更快。

如果你不确定使用哪一个,你可以使用一个多字段来将数据映射为keyword 数字数据类型。

基本关键词字段的参数

edit

以下参数由 keyword 字段接受:

doc_values
字段是否应以列步长方式存储在磁盘上,以便以后可以用于排序、聚合或脚本?接受 true(默认)或 false
eager_global_ordinals
全局序数是否应在刷新时立即加载?接受 truefalse(默认)。在经常用于词条聚合的字段上启用此功能是一个好主意。
fields
多字段允许将相同的字符串值以多种方式进行索引,以满足不同的目的,例如一个字段用于搜索,而另一个多字段用于排序和聚合。
ignore_above
不要索引任何长度超过此值的字符串。默认值为 2147483647,以便接受所有值。但请注意,默认的动态映射规则会创建一个子 keyword 字段,该字段通过设置 ignore_above: 256 来覆盖此默认值。
index
字段是否应快速可搜索?接受 true(默认)和 false。仅启用了 doc_valueskeyword 字段仍然可以查询,尽管速度较慢。
index_options
用于评分目的,索引中应存储哪些信息。 默认为docs,但也可以设置为freqs,以在计算分数时考虑词频。
meta
字段的相关元数据。
norms
是否在评分查询时考虑字段长度。 接受 truefalse(默认)。
null_value
接受一个字符串值,该值将替换任何显式的 null 值。默认为 null,这意味着该字段被视为缺失。请注意,如果使用了 script 值,则不能设置此项。
on_script_error
定义如果在索引时由script参数定义的脚本抛出错误时应执行的操作。接受fail(默认),这将导致整个文档被拒绝,以及continue,这将把字段注册在文档的_ignored元数据字段中并继续索引。此参数只能在设置了script字段时设置。
script
如果设置此参数,则该字段将索引由此脚本生成的值,而不是直接从源中读取值。如果在输入文档中为此字段设置了值,则文档将被拒绝并返回错误。 脚本格式与其运行时等效项相同。脚本发出的值将像往常一样进行规范化,如果它们的长度超过在ignore_above上设置的值,则将被忽略。
store
字段值是否应与_source字段分开存储和检索。接受truefalse(默认)。
similarity
使用哪种评分算法或相似度。默认为BM25
normalizer
如何在对关键词进行索引之前进行预处理。默认为 null, 表示关键词保持原样。
split_queries_on_whitespace
是否应在为此字段构建查询时,将全文查询的输入按空格分割。 接受truefalse(默认)。
time_series_dimension

(可选,布尔值)

将字段标记为时间序列维度。默认为false

索引设置 index.mapping.dimension_fields.limit 限制了索引中的维度数量。

维度字段具有以下约束:

  • The doc_values and index mapping parameters must be true.
  • 维度值用于标识文档的时间序列。如果在索引期间以任何方式更改维度值,文档将被存储为属于与预期不同的时间序列。因此,存在额外的约束:

合成 _source

edit

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

合成源可能会对keyword字段进行排序并删除重复项。 例如:

PUT idx
{
  "settings": {
    "index": {
      "mapping": {
        "source": {
          "mode": "synthetic"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "kwd": { "type": "keyword" }
    }
  }
}
PUT idx/_doc/1
{
  "kwd": ["foo", "foo", "bar", "baz"]
}

将变为:

{
  "kwd": ["bar", "baz", "foo"]
}

如果一个keyword字段将store设置为true,那么顺序和重复项将被保留。例如:

PUT idx
{
  "settings": {
    "index": {
      "mapping": {
        "source": {
          "mode": "synthetic"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "kwd": { "type": "keyword", "store": true }
    }
  }
}
PUT idx/_doc/1
{
  "kwd": ["foo", "foo", "bar", "baz"]
}

将变为:

{
  "kwd": ["foo", "foo", "bar", "baz"]
}

长度超过 ignore_above 的值会被保留,但会被排序到末尾。 例如:

PUT idx
{
  "settings": {
    "index": {
      "mapping": {
        "source": {
          "mode": "synthetic"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "kwd": { "type": "keyword", "ignore_above": 3 }
    }
  }
}
PUT idx/_doc/1
{
  "kwd": ["foo", "foo", "bang", "bar", "baz"]
}

将变为:

{
  "kwd": ["bar", "baz", "foo", "bang"]
}

常量关键词字段类型

edit

Constant keyword 是 keyword 字段的一个特化,适用于索引中所有文档具有相同值的情况。

PUT logs-debug
{
  "mappings": {
    "properties": {
      "@timestamp": {
        "type": "date"
      },
      "message": {
        "type": "text"
      },
      "level": {
        "type": "constant_keyword",
        "value": "debug"
      }
    }
  }
}

constant_keyword 支持与 keyword 字段相同的查询和聚合,但利用了所有文档在每个索引中具有相同值的事实,以更高效地执行查询。

提交没有字段值的文档或字段值等于映射中配置的值的文档都是允许的。以下两个索引请求是等效的:

POST logs-debug/_doc
{
  "date": "2019-12-12",
  "message": "Starting up Elasticsearch",
  "level": "debug"
}

POST logs-debug/_doc
{
  "date": "2019-12-12",
  "message": "Starting up Elasticsearch"
}

然而,提供一个与映射中配置的值不同的值是不允许的。

如果在映射中没有提供value,字段将根据第一个索引文档中包含的值自动配置自身。 虽然这种行为可能很方便,但请注意,这意味着如果一个有毒的文档具有错误的值,它可能会导致所有其他文档被拒绝。

在未提供值之前(无论是通过映射还是来自文档),对该字段的查询将不会匹配任何文档。这包括 exists 查询。

字段的在设置后不能更改。

常量关键词字段的参数

edit

接受的映射参数如下:

meta

字段的元数据。

与索引中所有文档关联的值。如果未提供此参数,则根据第一个被索引的文档设置。

通配符字段类型

edit

The wildcard 字段类型是一种专门的关键字字段,用于非结构化的机器生成内容,您计划使用类似 grep 的 wildcardregexp 查询进行搜索。wildcard 类型针对具有大值或高基数的字段进行了优化。

在内部,wildcard 字段使用 ngrams 对整个字段值进行索引并存储完整字符串。 索引用作粗略过滤器,以减少通过检索和检查完整值来检查的值的数量。 此字段特别适合在日志行上运行类似 grep 的查询。存储成本通常低于 keyword 字段,但对于完整术语的精确匹配搜索速度较慢。如果字段值共享许多前缀,例如同一网站的 URL,则 wildcard 字段的存储成本可能高于等效的 keyword 字段。

您可以按如下方式索引和搜索通配符字段

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "my_wildcard": {
        "type": "wildcard"
      }
    }
  }
}

PUT my-index-000001/_doc/1
{
  "my_wildcard" : "This string can be quite lengthy"
}

GET my-index-000001/_search
{
  "query": {
    "wildcard": {
      "my_wildcard": {
        "value": "*quite*lengthy"
      }
    }
  }
}

通配符字段的参数

edit

以下参数被wildcard字段接受:

null_value

接受一个字符串值,该值将替换任何显式的 null 值。默认为 null,这意味着该字段被视为缺失。

ignore_above

不要索引任何长度超过此值的字符串。默认值为 2147483647,以便接受所有值。

限制

edit
  • wildcard 字段像关键字字段一样未被分词,因此不支持依赖词位置的查询,如短语查询。
  • 当运行 wildcard 查询时,任何 rewrite 参数都会被忽略。评分始终是一个常数分数。

合成 _source

edit

合成源可能会对通配符字段值进行排序。例如:

PUT idx
{
  "settings": {
    "index": {
      "mapping": {
        "source": {
          "mode": "synthetic"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "card": { "type": "wildcard" }
    }
  }
}
PUT idx/_doc/1
{
  "card": ["king", "ace", "ace", "jack"]
}

将变为:

{
  "card": ["ace", "jack", "king"]
}

嵌套字段类型

edit

The nested type 是 object 数据类型的特殊版本, 它允许对象数组以一种可以彼此独立查询的方式进行索引。

当摄取具有大量任意键值对时,您可以考虑将每个键值对建模为其自己的嵌套文档,其中包含keyvalue字段。相反,考虑使用flattened数据类型,它将整个对象映射为单个字段,并允许对其内容进行简单搜索。嵌套文档和查询通常是昂贵的,因此在此用例中使用flattened数据类型是一个更好的选择。

嵌套字段在 Kibana 中的支持不完整。尽管它们在 Discover 中可见且可搜索,但无法在 Lens 中用于构建可视化。

对象数组如何被展平

edit

Elasticsearch 没有内部对象的概念。因此,它将对象层次结构扁平化为一个简单的字段名称和值的列表。例如,考虑以下文档:

PUT my-index-000001/_doc/1
{
  "group" : "fans",
  "user" : [ 
    {
      "first" : "John",
      "last" :  "Smith"
    },
    {
      "first" : "Alice",
      "last" :  "White"
    }
  ]
}

The user 字段被动态添加为类型为 object 的字段。

之前的文档将在内部转换为更像这样的文档:

{
  "group" :        "fans",
  "user.first" : [ "alice", "john" ],
  "user.last" :  [ "smith", "white" ]
}

字段 user.firstuser.last 被展平为多值字段, 并且 alicewhite 之间的关联丢失了。这个文档会 错误地匹配查询 alice AND smith

GET my-index-000001/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "user.first": "Alice" }},
        { "match": { "user.last":  "Smith" }}
      ]
    }
  }
}

使用 nested 字段处理对象数组

edit

如果你需要索引对象数组并保持数组中每个对象的独立性,请使用 nested 数据类型,而不是 object 数据类型。

在内部,嵌套对象将数组中的每个对象索引为单独的隐藏文档,这意味着可以使用nested查询独立查询每个嵌套对象:

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "user": {
        "type": "nested" 
      }
    }
  }
}

PUT my-index-000001/_doc/1
{
  "group" : "fans",
  "user" : [
    {
      "first" : "John",
      "last" :  "Smith"
    },
    {
      "first" : "Alice",
      "last" :  "White"
    }
  ]
}

GET my-index-000001/_search
{
  "query": {
    "nested": {
      "path": "user",
      "query": {
        "bool": {
          "must": [
            { "match": { "user.first": "Alice" }},
            { "match": { "user.last":  "Smith" }} 
          ]
        }
      }
    }
  }
}

GET my-index-000001/_search
{
  "query": {
    "nested": {
      "path": "user",
      "query": {
        "bool": {
          "must": [
            { "match": { "user.first": "Alice" }},
            { "match": { "user.last":  "White" }} 
          ]
        }
      },
      "inner_hits": { 
        "highlight": {
          "fields": {
            "user.first": {}
          }
        }
      }
    }
  }
}

The user 字段被映射为 nested 类型,而不是 object 类型。

此查询不匹配,因为 AliceSmith 不在同一个嵌套对象中。

此查询匹配,因为 AliceWhite 在同一个嵌套对象中。

inner_hits 允许我们突出显示匹配的嵌套文档。

嵌套文档交互

edit

嵌套文档可以是:

因为嵌套文档是作为单独的文档进行索引的,它们只能在 nested 查询、nested/reverse_nested 聚合或 嵌套内部命中 的范围内访问。

例如,如果嵌套文档中的字符串字段设置了 index_optionsoffsets,以允许在突出显示期间使用词频信息,这些偏移量在主突出显示阶段将不可用。相反,需要通过 嵌套内部命中 来执行突出显示。当通过 docvalue_fieldsstored_fields 在搜索期间加载字段时,同样需要考虑这一点。

嵌套字段的参数

edit

以下参数由 nested 字段接受:

dynamic
(可选,字符串) 是否应将新属性动态添加到现有嵌套对象中。接受true(默认)、falsestrict
properties
(可选, 对象) 嵌套对象中的字段, 可以是任何 数据类型, 包括 nested。可以向现有嵌套对象添加新属性。
include_in_parent
(可选,布尔值) 如果为true,嵌套对象中的所有字段也会作为标准(扁平)字段添加到父文档中。默认为false
include_in_root
(可选,布尔值) 如果为true,嵌套对象中的所有字段也会作为标准(扁平)字段添加到根文档中。默认为false

关于嵌套映射和对象的限制

edit

如前所述,每个嵌套对象都被索引为一个单独的Lucene文档。 继续前面的例子,如果我们索引了一个包含100个user对象的单个文档, 那么将创建101个Lucene文档:一个用于父文档,一个用于每个 嵌套对象。由于nested映射相关的开销,Elasticsearch设置了 一些措施来防止性能问题:

index.mapping.nested_fields.limit
索引中不同嵌套映射的最大数量。嵌套类型应仅在特殊情况下使用,当需要独立查询对象数组时。为了防止设计不良的映射,此设置限制了每个索引的唯一嵌套类型的数量。默认值为50

在前面的示例中,user 映射将仅计为 1 个此限制。

index.mapping.nested_objects.limit
单个文档在所有嵌套类型中可以包含的最大嵌套JSON对象数量。此限制有助于防止当文档包含过多嵌套对象时出现内存不足错误。默认值为10000

为了说明此设置的工作原理,请考虑在前一个示例映射中添加另一个名为 commentsnested 类型。对于每个文档,它包含的 usercomment 对象的总数必须低于限制。

关于防止映射爆炸的附加设置,请参阅防止映射爆炸

数值字段类型

edit

支持以下数值类型:

长整型

一个有符号的64位整数,最小值为 -263,最大值为 263-1

整数

一个有符号的32位整数,最小值为 -231,最大值为 231-1

短整型

一个有符号的16位整数,最小值为 -32,768,最大值为 32,767

字节

一个有符号的8位整数,最小值为-128,最大值为127

双精度

一个双精度64位IEEE 754浮点数,限制为有限值。

浮点数

一个单精度32位IEEE 754浮点数,限制为有限值。

半浮点数

一个半精度16位IEEE 754浮点数,限制为有限值。

scaled_float

一个由 long 支持的浮点数,通过固定的 double 缩放因子进行缩放。

无符号长整型

一个无符号的64位整数,最小值为0,最大值为264-1

下面是一个配置带有数值字段的映射的示例:

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "number_of_bytes": {
        "type": "integer"
      },
      "time_in_seconds": {
        "type": "float"
      },
      "price": {
        "type": "scaled_float",
        "scaling_factor": 100
      }
    }
  }
}

The double, float and half_float 类型认为 -0.0+0.0 是不同的值。因此,对 -0.0 进行 term 查询 将不会匹配 +0.0,反之亦然。范围查询也是如此: 如果上界是 -0.0,则 +0.0 不会匹配,如果下界是 +0.0,则 -0.0 不会匹配。

我应该使用哪种类型?

edit

就整数类型(byteshortintegerlong)而言, 您应该选择足够满足您使用场景的最小类型。这将有助于索引和搜索更加高效。但请注意,存储是基于实际存储的值进行优化的,因此选择一种类型而不是另一种类型不会对存储需求产生影响。

对于浮点类型,通常更高效的做法是使用缩放因子将浮点数据存储为整数,这就是scaled_float类型在底层所做的事情。例如,一个price字段可以存储在一个scaled_float中,缩放因子为100。所有API的操作都像该字段存储为双精度数一样,但在底层,Elasticsearch会使用以分为单位的数值,即price*100,这是一个整数。这主要是为了节省磁盘空间,因为整数比浮点数更容易压缩。scaled_float也可以用于以精度换取磁盘空间。例如,假设你正在跟踪CPU利用率,其值在01之间。通常情况下,CPU利用率是12.7%还是13%并不重要,因此你可以使用缩放因子为100scaled_float,以便将CPU利用率四舍五入到最近的百分比,从而节省空间。

如果 scaled_float 不适合,那么你应该选择浮点类型中最小的类型,以满足使用场景:doublefloathalf_float。以下是一个比较这些类型的表格,以帮助做出决策。

Type Minimum value Maximum value Significant
bits / digits
Example precision loss

双精度

2-1074

(2-2-52)·21023

53 / 15.95

1.2345678912345678
1.234567891234568

浮点数

2-149

(2-2-23)·2127

24 / 7.22

1.23456789
1.2345679

半浮点数

2-24

65504

11 / 3.31

1.2345
1.234375

映射数字标识符

并非所有数值数据都应映射为数值字段数据类型。 Elasticsearch 优化了数值字段,例如 integerlong,用于 range 查询。然而,keyword 字段 更适合 term 和其他 词项级别查询。

标识符,如ISBN或产品ID,很少用于范围查询。然而,它们通常使用术语级查询来检索。

如果满足以下条件,请考虑将数值标识符映射为keyword

  • 您不打算使用range查询来搜索标识符数据。
  • 快速检索很重要。term查询在keyword字段上的搜索通常比在数值字段上的term搜索更快。

如果你不确定使用哪一个,你可以使用一个多字段来将数据映射为keyword 数字数据类型。

数值字段的参数

edit

以下参数由数值类型接受:

coerce
尝试将字符串转换为数字并截断整数的分数部分。 接受 true(默认)和 false。不适用于 unsigned_long。 请注意,如果使用了 script 参数,则无法设置此项。
doc_values
字段是否应以列步长方式存储在磁盘上,以便以后可以用于排序、聚合或脚本?接受 true(默认)或 false
ignore_malformed
如果 true,格式错误的数字将被忽略。如果 false(默认),格式错误的数字将抛出异常并拒绝整个文档。请注意,如果使用了 script 参数,则无法设置此选项。
index
该字段是否应快速可搜索?接受 true(默认)和 false。仅启用了 doc_values 的数值字段也可以查询,尽管速度较慢。
meta
字段的相关元数据。
null_value
接受与字段相同类型的数值,用于替换任何显式的null值。默认为null,这意味着该字段被视为缺失。请注意,如果使用了script参数,则不能设置此项。
on_script_error
定义如果在索引时由script参数定义的脚本抛出错误时应执行的操作。接受fail(默认),这将导致整个文档被拒绝,以及continue,这将把字段注册在文档的_ignored元数据字段中并继续索引。此参数只能在设置了script字段时设置。
script
如果设置了此参数,则该字段将索引由此脚本生成的值,而不是直接从源中读取值。如果在输入文档中为此字段设置了值,则文档将被拒绝并返回错误。 脚本的格式与其运行时等效项相同。脚本只能配置在longdouble字段类型上。
store
字段值是否应与_source字段分开存储和检索。接受truefalse(默认)。
time_series_dimension

(可选,布尔值)

将字段标记为时间序列维度。默认为false

索引设置 index.mapping.dimension_fields.limit 限制了索引中的维度数量。

维度字段具有以下约束:

  • The doc_values and index mapping parameters must be true.

在数值字段类型中,只有 byteshortintegerlongunsigned_long 字段支持此参数。

数值字段不能同时是时间序列维度和时间序列指标。

time_series_metric

(可选,字符串) 将字段标记为时间序列指标。该值是指标类型。您不能更新现有字段的此参数。

数值型字段的有效 time_series_metric
counter
一种累积指标,仅单调递增或重置为 0(零)。例如,错误计数或已完成任务的计数。
gauge
表示可以任意增加或减少的单个数值的指标。例如,温度或可用磁盘空间。
null(默认)
不是时间序列指标。

对于数值型时间序列指标,doc_values 参数必须为 true。一个数值字段不能同时是时间序列维度和时间序列指标。

参数为 scaled_float

edit

scaled_float 接受一个额外的参数:

缩放因子

在编码值时使用的缩放因子。值将在索引时乘以这个因子并四舍五入到最接近的长整型值。例如,一个 scaled_float 类型,其 scaling_factor10,将会将 2.34 内部存储为 23,并且在搜索时所有操作(查询、聚合、排序)将表现得好像文档的值为 2.3。较高的 scaling_factor 值提高了精度,但也增加了空间需求。此参数是必需的。

scaled_float 饱和度

edit

scaled_float 存储为一个 long 值,该值是原始值乘以缩放因子的乘积。如果乘法结果超出了 long 的范围,则该值会饱和到 long 的最小值或最大值。例如,如果缩放因子是 100 且值为 92233720368547758.08,则预期值为 9223372036854775808。然而,存储的值是 9223372036854775807,即 long 的最大值。

这可能会导致在使用范围查询时出现意外结果,当缩放因子或提供的float值特别大时。

合成 _source

edit

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

所有数值字段在其默认配置中都支持合成 _source。合成_source不能与copy_to一起使用,也不能与doc_values禁用的情况一起使用。

合成源可能会对数值字段值进行排序。例如:

PUT idx
{
  "settings": {
    "index": {
      "mapping": {
        "source": {
          "mode": "synthetic"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "long": { "type": "long" }
    }
  }
}
PUT idx/_doc/1
{
  "long": [0, 0, -123466, 87612]
}

将变为:

{
  "long": [-123466, 0, 0, 87612]
}

缩放的浮点数将始终应用它们的缩放因子,因此:

PUT idx
{
  "settings": {
    "index": {
      "mapping": {
        "source": {
          "mode": "synthetic"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "f": { "type": "scaled_float", "scaling_factor": 0.01 }
    }
  }
}
PUT idx/_doc/1
{
  "f": 123
}

将变为:

{
  "f": 100.0
}

对象字段类型

edit

JSON文档本质上是分层的:文档可能包含内部对象,而这些内部对象本身可能包含内部对象:

PUT my-index-000001/_doc/1
{ 
  "region": "US",
  "manager": { 
    "age":     30,
    "name": { 
      "first": "John",
      "last":  "Smith"
    }
  }
}

外部文档也是一个JSON对象。

它包含一个名为 manager 的内部对象。

其中包含一个名为 name 的内部对象。

在内部,本文档被索引为一个简单的、扁平的键值对列表,类似于这样:

{
  "region":             "US",
  "manager.age":        30,
  "manager.name.first": "John",
  "manager.name.last":  "Smith"
}

上述文档的显式映射可能如下所示:

PUT my-index-000001
{
  "mappings": {
    "properties": { 
      "region": {
        "type": "keyword"
      },
      "manager": { 
        "properties": {
          "age":  { "type": "integer" },
          "name": { 
            "properties": {
              "first": { "type": "text" },
              "last":  { "type": "text" }
            }
          }
        }
      }
    }
  }
}

顶级映射定义中的属性。

The manager 字段是一个内部 object 字段。

The manager.name 字段是 manager 字段内的一个内部 object 字段。

您不需要将字段 type 显式设置为 object,因为这是默认值。

对象字段的参数

edit

以下参数由 object 字段接受:

dynamic

是否应将新属性动态添加到现有对象。接受true(默认)、runtimefalsestrict

enabled

对象字段给出的JSON值是否应被解析并索引(true,默认)或完全忽略(false)。

subobjects

对象是否可以包含子对象(true,默认)或不可以(false)。如果不可以,名称中带有点的子字段将被视为叶子节点,否则它们的字段名称将被扩展为其对应的对象结构。

properties

对象中的字段可以是任何 数据类型,包括 对象。可以向现有对象添加新属性。

如果你需要索引对象数组而不是单个对象,请先阅读嵌套

透传对象字段类型

edit

传递对象通过允许在不包含传递对象名称作为前缀的情况下访问其子字段,扩展了对象的功能。例如:

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "attributes": {
        "type": "passthrough", 
        "priority": 10,
        "properties": {
          "id": {
            "type": "keyword"
          }
        }
      }
    }
  }
}

PUT my-index-000001/_doc/1
{
  "attributes" : {  
    "id": "foo",
    "zone": 10
  }
}

GET my-index-000001/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "id": "foo" }},  
        { "match": { "zone": 10 }}
      ]
    }
  }
}

GET my-index-000001/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "attributes.id": "foo" }}, 
        { "match": { "attributes.zone": 10 }}
      ]
    }
  }
}

对象被定义为透传。其优先级(必需)用于冲突解决。

对象内容按常规方式进行索引,包括动态映射。

子字段可以在查询中引用,就像它们在根级别定义一样。

子字段也可以被引用,包括对象名称作为前缀。

冲突解决

edit

可能会出现名称冲突的情况,这些字段定义在不同的作用域内:

  1. 透传对象定义在与透传对象子字段相同名称的字段旁边,例如。

    PUT my-index-000001/_doc/1
    {
      "attributes" : {
        "id": "foo"
      },
      "id": "bar"
    }

    在这种情况下,对 id 的引用指向根级别的字段,而字段 attributes.id 只能通过完整路径访问。

  2. 在同一个对象内定义了两个(或更多)透传对象,并且它们包含具有相同名称的字段,例如。

    PUT my-index-000002
    {
      "mappings": {
        "properties": {
          "attributes": {
            "type": "passthrough",
            "priority": 10,
            "properties": {
              "id": {
                "type": "keyword"
              }
            }
          },
          "resource.attributes": {
            "type": "passthrough",
            "priority": 20,
            "properties": {
              "id": {
                "type": "keyword"
              }
            }
          }
        }
      }
    }

    在这种情况下,参数priority用于冲突解决,值较高的优先级更高。在上面的示例中,resource.attributes的优先级高于attributes,因此对id的引用指向resource.attributes字段内的字段。attributes.id仍然可以通过其完整路径访问。

将子字段定义为时间序列维度

edit

可以将透传字段配置为 时间序列维度 的容器。 在这种情况下,所有子字段在幕后都会被标注为相同的参数,并且它们也会被包含在 基于维度的路由路径tsid 计算中,从而简化了 TSDS 的设置:

PUT _index_template/my-metrics
{
  "index_patterns": ["metrics-mymetrics-*"],
  "priority": 200,
  "data_stream": { },
  "template": {
    "settings": {
      "index.mode": "time_series"
    },
    "mappings": {
      "properties": {
        "attributes": {
          "type": "passthrough",
          "priority": 10,
          "time_series_dimension": true,
          "properties": {
            "host.name": {
              "type": "keyword"
            }
          }
        },
        "cpu": {
          "type": "integer",
          "time_series_metric": "counter"
        }
      }
    }
  }
}

POST metrics-mymetrics-test/_doc
{
  "@timestamp": "2020-01-01T00:00:00.000Z",
  "attributes" : {
    "host.name": "foo",
    "zone": "bar"
  },
  "cpu": 10
}

在上面的示例中,attributes 被定义为一个维度容器。它的子字段 host.name(静态)和 zone(动态)被包含在路由路径和tsid中,并且可以在查询中引用,而无需使用 attributes. 前缀。

子字段自动展平

edit

传递字段默认对子字段应用自动展平,以减少动态映射冲突。因此,传递字段内不允许定义子对象。

用于passthrough字段的参数

edit

以下参数由 passthrough 字段接受:

priority

(必需) 用于解决透传字段之间的命名冲突。值最高的字段获胜。 接受非负整数值。

time_series_dimension

是否将子字段视为时间序列维度。 接受 false(默认)或 true

dynamic

是否应将新属性动态添加到现有对象。 接受true(默认)、runtimefalsestrict

enabled

对象字段给出的JSON值是否应被解析并索引(true,默认) 或完全忽略(false)。

properties

对象中的字段可以是任何数据类型,包括对象。 可以向现有对象添加新属性。

如果你需要索引对象数组而不是单个对象,请先阅读嵌套

Percolator 字段类型

edit

The percolator 字段类型将一个json结构解析为一个本地查询并存储该查询,以便percolate query可以使用它来匹配提供的文档。

任何包含json对象的字段都可以配置为percolator字段。percolator字段类型没有设置。只需配置percolator字段类型就足以指示Elasticsearch将字段视为查询。

如果以下映射配置了query字段的percolator字段类型:

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "query": {
        "type": "percolator"
      },
      "field": {
        "type": "text"
      }
    }
  }
}

然后你可以索引一个查询:

PUT my-index-000001/_doc/match_value
{
  "query": {
    "match": {
      "field": "value"
    }
  }
}

在 percolator 查询中引用的字段必须已经存在于与索引关联的映射中。为了确保这些字段存在,可以通过创建索引更新映射 API 添加或更新映射。

重新索引你的 percolator 查询

edit

重新索引 percolator 查询有时是必要的,以利用新版本中对 percolator 字段类型所做的改进。

可以通过使用reindex api来重新索引percolator查询。 让我们来看一下以下具有percolator字段类型的索引:

PUT index
{
  "mappings": {
    "properties": {
      "query" : {
        "type" : "percolator"
      },
      "body" : {
        "type": "text"
      }
    }
  }
}

POST _aliases
{
  "actions": [
    {
      "add": {
        "index": "index",
        "alias": "queries" 
      }
    }
  ]
}

PUT queries/_doc/1?refresh
{
  "query" : {
    "match" : {
      "body" : "quick brown fox"
    }
  }
}

始终建议为您的索引定义一个别名,这样在重新索引的情况下,系统/应用程序不需要更改即可知道 percolator 查询现在位于不同的索引中。

假设你要升级到一个新的主要版本,为了让新的 Elasticsearch 版本仍然能够读取你的查询,你需要在当前的 Elasticsearch 版本上将查询重新索引到一个新的索引中:

PUT new_index
{
  "mappings": {
    "properties": {
      "query" : {
        "type" : "percolator"
      },
      "body" : {
        "type": "text"
      }
    }
  }
}

POST /_reindex?refresh
{
  "source": {
    "index": "index"
  },
  "dest": {
    "index": "new_index"
  }
}

POST _aliases
{
  "actions": [ 
    {
      "remove": {
        "index" : "index",
        "alias": "queries"
      }
    },
    {
      "add": {
        "index": "new_index",
        "alias": "queries"
      }
    }
  ]
}

如果你有一个别名,别忘了将其指向新的索引。

通过 queries 别名执行 percolate 查询:

GET /queries/_search
{
  "query": {
    "percolate" : {
      "field" : "query",
      "document" : {
        "body" : "fox jumps over the lazy dog"
      }
    }
  }
}

现在返回来自新索引的匹配项:

{
  "took": 3,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped" : 0,
    "failed": 0
  },
  "hits": {
    "total" : {
        "value": 1,
        "relation": "eq"
    },
    "max_score": 0.13076457,
    "hits": [
      {
        "_index": "new_index", 
        "_id": "1",
        "_score": 0.13076457,
        "_source": {
          "query": {
            "match": {
              "body": "quick brown fox"
            }
          }
        },
        "fields" : {
          "_percolator_document_slot" : [0]
        }
      }
    ]
  }
}

Percolator 查询命中现在来自新索引。

优化查询时间文本分析

edit

当 percolator 验证一个 percolator 候选匹配时,它将解析、执行查询时文本分析,并在被 percolated 的文档上实际运行 percolator 查询。这是为每个候选匹配完成的,并且每次执行 percolate 查询时都会进行。如果你的查询时文本分析是查询解析中相对昂贵的部分,那么文本分析可能会成为 percolating 时花费时间的主要因素。当 percolator 最终验证许多候选 percolator 查询匹配时,这种查询解析开销可能会变得明显。

为了避免在渗透时间进行文本分析中最昂贵的部分。可以选择在索引渗透器查询时进行文本分析的昂贵部分。这需要使用两种不同的分析器。第一个分析器实际上执行需要执行的文本分析(昂贵部分)。第二个分析器(通常是空格)只是分割第一个分析器生成的标记。然后,在索引渗透器查询之前,应使用分析API以更昂贵的分析器分析查询文本。分析API的结果,即标记,应用于替换渗透器查询中的原始查询文本。重要的是,查询现在应配置为覆盖映射中的分析器,并仅使用第二个分析器。大多数基于文本的查询支持一个analyzer选项(matchquery_stringsimple_query_string)。使用这种方法,昂贵的文本分析只需执行一次,而不是多次。

让我们通过一个简化的例子来演示这个工作流程。

假设我们要索引以下 percolator 查询:

{
  "query" : {
    "match" : {
      "body" : {
        "query" : "missing bicycles"
      }
    }
  }
}

使用这些设置和映射:

PUT /test_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_analyzer" : {
          "tokenizer": "standard",
          "filter" : ["lowercase", "porter_stem"]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "query" : {
        "type": "percolator"
      },
      "body" : {
        "type": "text",
        "analyzer": "my_analyzer" 
      }
    }
  }
}

为了这个示例的目的,这个分析器被认为是昂贵的。

首先,我们需要使用分析 API 在索引之前执行文本分析:

POST /test_index/_analyze
{
  "analyzer" : "my_analyzer",
  "text" : "missing bicycles"
}

这将产生以下响应:

{
  "tokens": [
    {
      "token": "miss",
      "start_offset": 0,
      "end_offset": 7,
      "type": "<ALPHANUM>",
      "position": 0
    },
    {
      "token": "bicycl",
      "start_offset": 8,
      "end_offset": 16,
      "type": "<ALPHANUM>",
      "position": 1
    }
  ]
}

返回的订单中的所有令牌都需要替换渗透器查询中的查询文本:

PUT /test_index/_doc/1?refresh
{
  "query" : {
    "match" : {
      "body" : {
        "query" : "miss bicycl",
        "analyzer" : "whitespace" 
      }
    }
  }
}

在这里选择一个空白分析器是很重要的,否则将使用映射中定义的分析器,这将违背使用此工作流程的目的。请注意,whitespace 是一个内置分析器,如果需要使用不同的分析器,则需要首先在索引的设置中进行配置。

在索引 percolator 流程之前,应该对每个 percolator 查询进行分析 API 处理。

在渗透时间没有任何变化,percolate 查询可以正常定义:

GET /test_index/_search
{
  "query": {
    "percolate" : {
      "field" : "query",
      "document" : {
        "body" : "Bycicles are missing"
      }
    }
  }
}

这将产生如下响应:

{
  "took": 6,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped" : 0,
    "failed": 0
  },
  "hits": {
    "total" : {
        "value": 1,
        "relation": "eq"
    },
    "max_score": 0.13076457,
    "hits": [
      {
        "_index": "test_index",
        "_id": "1",
        "_score": 0.13076457,
        "_source": {
          "query": {
            "match": {
              "body": {
                "query": "miss bicycl",
                "analyzer": "whitespace"
              }
            }
          }
        },
        "fields" : {
          "_percolator_document_slot" : [0]
        }
      }
    ]
  }
}

优化通配符查询。

edit

通配符查询对于 percolator 来说比其他查询更耗费资源,特别是当通配符表达式很大时。

在带有前缀通配符表达式的通配符查询或仅前缀查询的情况下,可以使用edge_ngram分词过滤器将这些查询替换为在配置了edge_ngram分词过滤器的字段上的常规term查询。

创建带有自定义分析设置的索引:

PUT my_queries1
{
  "settings": {
    "analysis": {
      "analyzer": {
        "wildcard_prefix": { 
          "type": "custom",
          "tokenizer": "standard",
          "filter": [
            "lowercase",
            "wildcard_edge_ngram"
          ]
        }
      },
      "filter": {
        "wildcard_edge_ngram": { 
          "type": "edge_ngram",
          "min_gram": 1,
          "max_gram": 32
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "query": {
        "type": "percolator"
      },
      "my_field": {
        "type": "text",
        "fields": {
          "prefix": { 
            "type": "text",
            "analyzer": "wildcard_prefix",
            "search_analyzer": "standard"
          }
        }
      }
    }
  }
}

仅在索引时生成前缀标记的分析器。

根据您的前缀搜索需求,增加min_gram并减少max_gram设置。

此多字段应用于使用 termmatch 查询进行前缀搜索,而不是使用 prefixwildcard 查询。

然后,不索引以下查询:

{
  "query": {
    "wildcard": {
      "my_field": "abc*"
    }
  }
}

下面的查询应该被索引:

PUT /my_queries1/_doc/1?refresh
{
  "query": {
    "term": {
      "my_field.prefix": "abc"
    }
  }
}

这种方式可以比第一个查询更高效地处理第二个查询。

以下搜索请求将与之前索引的 percolator 查询匹配:

GET /my_queries1/_search
{
  "query": {
    "percolate": {
      "field": "query",
      "document": {
        "my_field": "abcd"
      }
    }
  }
}
{
  "took": 6,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total" : {
        "value": 1,
        "relation": "eq"
    },
    "max_score": 0.18864399,
    "hits": [
      {
        "_index": "my_queries1",
        "_id": "1",
        "_score": 0.18864399,
        "_source": {
          "query": {
            "term": {
              "my_field.prefix": "abc"
            }
          }
        },
        "fields": {
          "_percolator_document_slot": [
            0
          ]
        }
      }
    ]
  }
}

同样的技术也可以用于加速后缀通配符搜索。通过在使用 edge_ngram 分词器之前使用 reverse 分词器。

PUT my_queries2
{
  "settings": {
    "analysis": {
      "analyzer": {
        "wildcard_suffix": {
          "type": "custom",
          "tokenizer": "standard",
          "filter": [
            "lowercase",
            "reverse",
            "wildcard_edge_ngram"
          ]
        },
        "wildcard_suffix_search_time": {
          "type": "custom",
          "tokenizer": "standard",
          "filter": [
            "lowercase",
            "reverse"
          ]
        }
      },
      "filter": {
        "wildcard_edge_ngram": {
          "type": "edge_ngram",
          "min_gram": 1,
          "max_gram": 32
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "query": {
        "type": "percolator"
      },
      "my_field": {
        "type": "text",
        "fields": {
          "suffix": {
            "type": "text",
            "analyzer": "wildcard_suffix",
            "search_analyzer": "wildcard_suffix_search_time" 
          }
        }
      }
    }
  }
}

在搜索时也需要一个自定义分析器,因为否则查询词不会被反转,并且不会与保留的后缀标记匹配。

然后,不索引以下查询:

{
  "query": {
    "wildcard": {
      "my_field": "*xyz"
    }
  }
}

以下查询应被索引:

PUT /my_queries2/_doc/2?refresh
{
  "query": {
    "match": { 
      "my_field.suffix": "xyz"
    }
  }
}

应该使用 match 查询而不是 term 查询,因为需要对查询词进行文本分析。

以下搜索请求将与之前索引的 percolator 查询匹配:

GET /my_queries2/_search
{
  "query": {
    "percolate": {
      "field": "query",
      "document": {
        "my_field": "wxyz"
      }
    }
  }
}

专用渗透器索引

edit

Percolate 查询可以添加到任何索引中。与将 percolate 查询添加到数据所在的索引不同,这些查询也可以添加到一个专用的索引中。这样做的好处是,这个专用的 percolator 索引可以有自己的索引设置(例如主分片和副本分片的数量)。如果你选择使用专用的 percolate 索引,你需要确保普通索引的映射也在 percolate 索引中可用。否则,percolate 查询可能会被错误解析。

强制未映射字段作为字符串处理

edit

在某些情况下,无法确定会注册哪种类型的 percolator 查询,如果 percolator 查询引用的字段没有字段映射,则添加 percolator 查询会失败。这意味着需要更新映射以包含具有适当设置的字段,然后才能添加 percolator 查询。但有时,如果所有未映射的字段都被视为默认文本字段,就足够了。在这种情况下,可以将 index.percolator.map_unmapped_fields_as_text 设置为 true(默认为 false),然后如果 percolator 查询中引用的字段不存在,它将被视为默认文本字段,从而添加 percolator 查询不会失败。

限制

edit
父/子
edit

因为percolate查询是逐个处理文档的,所以它不支持针对子文档运行的查询和过滤器,例如has_childhas_parent

获取查询
edit

在查询解析期间,有许多查询通过get调用来获取数据。例如,使用terms lookup时的terms查询,使用索引脚本时的template查询,以及使用预索引形状时的geo_shape查询。当这些查询被percolator字段类型索引时,get调用只执行一次。因此,每次percolator查询评估这些查询时,都会使用索引时获取的术语、形状等。需要注意的是,这些查询每次在主分片和副本分片上索引percolator查询时,都会进行术语的获取,因此实际索引的术语在分片副本之间可能会有所不同,如果在索引期间源索引发生了变化。

脚本查询
edit

script 查询中的脚本只能访问 doc values 字段。percolate 查询将提供的文档索引到内存中的索引中。这个内存中的索引不支持存储字段,因此 _source 字段和其他存储字段不会被存储。这就是为什么在 script 查询中 _source 和其他存储字段不可用的原因。

字段别名
edit

包含字段别名的Percolator查询可能不会总是按预期行为执行。特别是,如果注册了一个包含字段别名的Percolator查询,然后在该映射中更新该别名以引用不同的字段,存储的查询仍将引用原始目标字段。要获取字段别名的更改,必须显式地重新索引Percolator查询。

点字段类型

edit

The point 数据类型有助于索引和搜索 任意 x, y 对,这些对位于二维平面坐标系中。

您可以使用形状查询来查询此类文档。

geo_shapegeo_point一样,point可以在GeoJSONWell-Known Text格式中指定。 然而,出于便利和历史原因,还支持许多其他格式。 总共有五种方式可以指定一个笛卡尔点,如下所示:

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "location": {
        "type": "point"
      }
    }
  }
}

PUT my-index-000001/_doc/1
{
  "text": "Point as an object using GeoJSON format",
  "location": { 
    "type": "Point",
    "coordinates": [-71.34, 41.12]
  }
}

PUT my-index-000001/_doc/2
{
  "text": "Point as a WKT POINT primitive",
  "location" : "POINT (-71.34 41.12)" 
}

PUT my-index-000001/_doc/3
{
  "text": "Point as an object with 'x' and 'y' keys",
  "location": { 
    "x": -71.34,
    "y": 41.12
  }
}

PUT my-index-000001/_doc/4
{
  "text": "Point as an array",
  "location": [ -71.34, 41.12 ] 
}

PUT my-index-000001/_doc/5
{
  "text": "Point as a string",
  "location": "-71.34,41.12" 
}

点表示为一个对象,采用GeoJSON格式,包含typecoordinates键。

点表示为Well-Known Text 格式为:"POINT(x y)"

点表示为一个对象,包含xy键。

点表示为数组,格式为:[ x, y]

点表示为字符串,格式为:"x,y"

geo-point字段类型的情况不同, 坐标xy的顺序在上述所有格式中都是相同的。

提供给索引器的坐标是单精度浮点值,因此该字段保证了与Java虚拟机提供的相同的精度(通常为1E-38)。

point 字段的参数

edit

以下参数由 point 字段接受:

ignore_malformed

如果true,格式错误的点将被忽略。如果false(默认),格式错误的点将抛出异常并拒绝整个文档。

ignore_z_value

如果为true(默认值),将接受三维点(存储在源中),但仅索引x和y值;忽略第三维度。如果为false,则包含超过x和y(二维)值的点将抛出异常并拒绝整个文档。

null_value

接受一个点值,该值将替换任何显式的 null 值。 默认为 null,这意味着该字段被视为缺失。

排序和检索点

edit

目前无法直接对点进行排序或检索它们的字段。point 值只能通过 _source 字段检索。

范围字段类型

edit

范围字段类型表示一个在上下限之间的连续值范围。例如,一个范围可以表示十月的任何日期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纪元以来的毫秒数的无符号64位整数。包含 now 日期数学 表达式的值不受支持。

ip_range

支持IPv4IPv6(或混合)地址的一系列IP值。

下面是一个配置包含各种范围字段的映射的示例,随后是一个索引多个范围类型的示例。

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字段上进行的术语查询示例。 12 是范围内的一个值,因此它将匹配。

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查询的示例。

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 范围

edit

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

PUT range_index/_mapping
{
  "properties": {
    "ip_allowlist": {
      "type": "ip_range"
    }
  }
}

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

范围字段的参数

edit

以下参数由范围类型接受:

coerce

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

doc_values

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

index

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

store

字段值是否应与_source字段分开存储和检索。接受truefalse(默认)。

合成 _source

edit

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

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

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

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 地址。

例如:

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。即使范围边界是显式提供的,这也是正确的。例如:

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。即使范围边界明确提供了默认值,这也是成立的。例如:

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 格式。例如:

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"
    }
  ]
}

排名特征字段类型

edit

一个 rank_feature 字段可以索引数字,以便它们可以在查询中用于提升文档,使用 rank_feature 查询。

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "pagerank": {
        "type": "rank_feature" 
      },
      "url_length": {
        "type": "rank_feature",
        "positive_score_impact": false 
      }
    }
  }
}

PUT my-index-000001/_doc/1
{
  "pagerank": 8,
  "url_length": 22
}

GET my-index-000001/_search
{
  "query": {
    "rank_feature": {
      "field": "pagerank"
    }
  }
}

排名特征字段必须使用 rank_feature 字段类型

需要声明与得分负相关的特征排名

rank_feature 字段仅支持单值字段和严格正值。多值字段和负值将被拒绝。

rank_feature 字段不支持查询、排序或聚合。它们只能在 rank_feature 查询中使用。

rank_feature 字段仅保留9个有效位用于精度,这相当于大约0.4%的相对误差。

与得分负相关的特征应将positive_score_impact设置为false(默认为true)。这将由rank_feature查询使用,以修改评分公式,使得得分随着特征值的增加而减少,而不是增加。例如,在网络搜索中,URL长度是一个常用的特征,它与得分呈负相关。

排名特征字段类型

edit

一个 rank_features 字段可以索引数值特征向量,以便在查询中使用 rank_feature 查询时提升文档。

它类似于rank_feature数据类型,但在特征列表稀疏的情况下更适合,因此为每个特征添加一个字段到映射中是不合理的。

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "topics": {
        "type": "rank_features" 
      },
      "negative_reviews" : {
        "type": "rank_features",
        "positive_score_impact": false 
      }
    }
  }
}

PUT my-index-000001/_doc/1
{
  "topics": { 
    "politics": 20,
    "economics": 50.8
  },
  "negative_reviews": {
    "1star": 10,
    "2star": 100
  }
}

PUT my-index-000001/_doc/2
{
  "topics": {
    "politics": 5.2,
    "sports": 80.1
  },
  "negative_reviews": {
    "1star": 1,
    "2star": 10
  }
}

GET my-index-000001/_search
{
  "query": { 
    "rank_feature": {
      "field": "topics.politics"
    }
  }
}

GET my-index-000001/_search
{
  "query": { 
    "rank_feature": {
      "field": "negative_reviews.1star"
    }
  }
}

GET my-index-000001/_search
{
  "query": { 
    "term": {
      "topics": "economics"
    }
  }
}

Rank features 字段必须使用 rank_features 字段类型

需要声明与得分负相关的特征排名

排序特征字段必须是一个带有字符串键和严格正数值的哈希

此查询根据文档与“政治”主题的相关程度对文档进行排名。

此查询根据文档收到的“1星”评论数量对其进行反向排名。

此查询返回在“topics”字段中存储“economics”特征的文档。

rank_features 字段仅支持单值特征和严格正值。多值字段以及零或负值将被拒绝。

rank_features 字段不支持排序或聚合,并且只能使用 rank_featureterm 查询进行查询。

term 查询在 rank_features 字段上的评分是通过将匹配的存储特征值与提供的 boost 相乘来计算的。

rank_features 字段仅保留9个有效位用于精度,这相当于大约0.4%的相对误差。

与得分负相关的特征应将positive_score_impact设置为false(默认为true)。这将由rank_feature查询用于修改评分公式,使得得分随着特征值的增加而减少,而不是增加。

即时搜索字段类型

edit

The search_as_you_type 字段类型是一种类似于文本的字段,它经过优化,可以提供开箱即用的支持,用于处理服务于“边输入边搜索”用例的查询。它会创建一系列子字段,这些子字段经过分析以索引术语,这些术语可以通过部分匹配整个索引文本值的查询进行高效匹配。支持前缀补全(即匹配从输入开头开始的术语)和中间补全(即匹配输入中任何位置的术语)。

当向映射中添加此类型的字段时

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "my_field": {
        "type": "search_as_you_type"
      }
    }
  }
}

这将创建以下字段

my_field

按照映射中的配置进行分析。如果未配置分析器,则使用索引的默认分析器

my_field._2gram

my_field 的分析器包装在一个大小为 2 的 shingle 词元过滤器中

my_field._3gram

my_field 的分析器包装在一个大小为 3 的 shingle 词元过滤器中

my_field._index_prefix

my_field._3gram 的分析器包装在一个边缘 ngram 分词过滤器中

子字段中的平铺大小可以通过 max_shingle_size 映射参数进行配置。默认值为 3,该参数的有效值为 2 到 4 之间的整数。将为每个从 2 到 max_shingle_size 的平铺大小创建平铺子字段。my_field._index_prefix 子字段在构建自己的分析器时,总是使用具有 max_shingle_size 的平铺子字段的分析器。

增加 max_shingle_size 将提高对包含更多连续词的查询的匹配度,但代价是索引大小会变大。默认的 max_shingle_size 通常已经足够。

相同的输入文本会自动索引到这些字段中的每一个,当索引文档具有根字段my_field的值时,它们会使用不同的分析链。

PUT my-index-000001/_doc/1?refresh
{
  "my_field": "quick brown fox jump lazy dog"
}

实现搜索即用型用例的最有效查询方式通常是类型为multi_match的查询,其类型为bool_prefix,目标为根search_as_you_type字段及其子字段。这可以匹配查询词的任何顺序,但如果它们在子字段中按顺序包含这些词,则会对文档进行更高的评分。

GET my-index-000001/_search
{
  "query": {
    "multi_match": {
      "query": "brown f",
      "type": "bool_prefix",
      "fields": [
        "my_field",
        "my_field._2gram",
        "my_field._3gram"
      ]
    }
  }
}
{
  "took" : 44,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 0.8630463,
    "hits" : [
      {
        "_index" : "my-index-000001",
        "_id" : "1",
        "_score" : 0.8630463,
        "_source" : {
          "my_field" : "quick brown fox jump lazy dog"
        }
      }
    ]
  }
}

要搜索严格按顺序匹配查询词的文档,或使用短语查询的其他属性进行搜索,请在根字段上使用match_phrase_prefix查询。如果最后一个词应完全匹配,而不是作为前缀,也可以使用match_phrase查询。使用短语查询可能不如使用match_bool_prefix查询高效。

GET my-index-000001/_search
{
  "query": {
    "match_phrase_prefix": {
      "my_field": "brown f"
    }
  }
}

特定于 search_as_you_type 字段的参数

edit

以下参数在映射中被接受用于search_as_you_type字段,并且是此字段类型特有的

max_shingle_size

(可选,整数) 创建的最大shingle大小。有效值为2(包含)到4 (包含)。默认为3

为每个介于 2 和此值之间的整数创建一个子字段。例如,值为 3 会创建两个子字段:my_field._2grammy_field._3gram

更多的子字段可以实现更具体的查询,但会增加索引大小。

作为文本字段的字段类型的参数

edit

由于search_as_you_type字段的文本特性,映射中接受以下参数,并且它们在配置text数据类型字段时的行为类似。除非另有说明,这些选项以相同的方式配置根字段的子字段。

analyzer
用于text字段的分析器,在索引时和搜索时都应使用(除非被search_analyzer覆盖)。默认值为默认索引分析器,或标准分析器
index
字段是否可搜索?接受 true(默认)或 false
index_options
应将哪些信息存储在索引中,以便用于搜索和突出显示。默认为 positions
norms
Whether field-length should be taken into account when scoring queries. Accepts true or false. This option configures the root field and shingle subfields, where its default is true. It does not configure the prefix subfield, where it is false.
store
字段值是否应与_source字段分开存储和检索。接受truefalse(默认)。此选项仅配置根字段,并不配置任何子字段。
search_analyzer
在搜索时应使用的分析器 文本字段。默认为分析器设置。
search_quote_analyzer
在搜索时遇到短语时应使用的分析器。默认为search_analyzer设置。
similarity
使用哪种评分算法或相似度。默认为BM25
term_vector
是否应为该字段存储词向量。默认为。此选项配置根字段和子字段,但不配置前缀子字段。

前缀查询的优化

edit

当对根字段或其任何子字段进行 prefix 查询时,查询将被重写为对 ._index_prefix 子字段的 term 查询。这比通常在文本字段上进行的 prefix 查询更高效,因为每个分词的前缀长度达到一定长度时,会直接作为 ._index_prefix 子字段中的词项进行索引。

._index_prefix 子字段的分析器稍微修改了构建 shingles 的行为,以便在字段值末尾的术语通常不会作为 shingles 生成时,也会索引这些术语的前缀。例如,如果将值 quick brown fox 索引到一个 search_as_you_type 字段中,并且 max_shingle_size 为 3,则 brown foxfox 的前缀也会被索引到 ._index_prefix 子字段中,即使它们没有出现在 ._3gram 子字段中。这允许完成字段输入中的所有术语。

合成 _source

edit

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

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

语义文本字段类型

edit

此功能处于测试阶段,可能会发生变化。设计和代码不如正式发布的功能成熟,并且是按原样提供的,不提供任何保证。测试功能不受正式发布功能的支持服务级别协议的约束。

The semantic_text 字段类型使用推理端点自动为文本内容生成嵌入。 长段落会被自动分块为较小的部分,以实现对更大文本语料库的处理。

The semantic_text 字段类型指定将用于生成嵌入的推理端点标识符。 您可以通过使用 Create inference API 来创建推理端点。 此字段类型和 semantic 查询 类型使得对您的数据进行语义搜索变得更加简单。

使用semantic_text,您不需要指定如何生成数据的嵌入,或如何对其进行索引。推理端点会自动确定要使用的嵌入生成、索引和查询。

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "inference_field": {
        "type": "semantic_text",
        "inference_id": "my-elser-endpoint"
      }
    }
  }
}

使用semantic_text的推荐方式是为摄取和搜索设置专门的推理端点。 这确保了搜索速度不受摄取工作负载的影响,反之亦然。 在为两者创建专门的推理端点后,您可以在为使用semantic_text字段的索引设置索引映射时,使用inference_idsearch_inference_id参数来引用它们。

PUT my-index-000002
{
  "mappings": {
    "properties": {
      "inference_field": {
        "type": "semantic_text",
        "inference_id": "my-elser-endpoint-for-ingest",
        "search_inference_id": "my-elser-endpoint-for-search"
      }
    }
  }
}

semantic_text 字段的参数

edit
inference_id
(必需,字符串) 将用于为字段生成嵌入的推理端点。 此参数无法更新。 使用创建推理API来创建端点。 如果指定了search_inference_id,则由inference_id定义的推理端点将仅在索引时使用。
search_inference_id
(可选, 字符串) 推理端点,将在查询时用于生成嵌入。 您可以使用更新映射 API来更新此参数。 使用创建推理 API来创建端点。 如果未指定,将在索引和查询时使用由inference_id定义的推理端点。

推理端点验证

edit

在创建映射时,inference_id 不会被验证,而是在将文档索引到索引中时进行验证。 当第一个文档被索引时,inference_id 将用于为该字段生成底层索引结构。

删除推理端点将导致在定义了semantic_text字段且将该推理端点作为其inference_id的索引上,文档摄取和语义查询失败。 尝试删除一个在semantic_text字段上使用的推理端点将导致错误。

自动文本分块

edit

推理端点对它们可以处理的文本量有限制。 为了允许在语义搜索中使用大量文本,semantic_text 会自动生成较小的段落(如果需要),称为

每个块将包含文本子段落及其生成的相应嵌入。 在查询时,每个文档的各个段落将自动进行搜索,并使用最相关的段落来计算得分。

文档被分割成250个词的部分,每部分之间有100个词的重叠,这样每个部分都与前一部分共享100个词。 这种重叠确保了连续性,并防止输入文本中的重要上下文信息因硬性分隔而丢失。

semantic_text 结构

edit

一旦文档被摄取,semantic_text 字段将具有以下结构:

"inference_field": {
  "text": "these are not the droids you're looking for", 
  "inference": {
    "inference_id": "my-elser-endpoint", 
    "model_settings": { 
      "task_type": "sparse_embedding"
    },
    "chunks": [ 
      {
        "text": "these are not the droids you're looking for",
        "embeddings": {
          (...)
        }
      }
    ]
  }
}

该字段将变为一个对象结构,以容纳原始文本和推理结果。

用于生成嵌入的 inference_id

模型设置,包括任务类型和维度/相似性(如果适用)。

推理结果将按块分组,每个块都有其对应的文本和嵌入。

请参考本教程以了解更多关于使用semantic_textsemantic查询进行语义搜索的信息。

自定义 semantic_text 索引

edit

semantic_text 使用基于指定推理端点的默认值来索引数据。它使您能够通过提供自动推理和专用查询来快速启动语义搜索,而无需提供进一步的详细信息。

如果您想自定义数据索引,请使用 sparse_vectordense_vector 字段类型,并创建一个包含 推理处理器 的摄取管道来生成嵌入。 本教程 将带您了解整个过程。在这些情况下 - 当您使用 sparse_vectordense_vector 字段类型而不是 semantic_text 字段类型来自定义索引时 - 不支持使用 semantic_query 来查询字段数据。

更新到 semantic_text 字段

edit

不支持对包含semantic_text字段的索引使用脚本进行更新。 即使脚本针对的是非semantic_text字段,当索引包含semantic_text字段时,更新也会失败。

copy_to 支持

edit

semantic_text 字段类型可以是 copy_to 字段的目标。这意味着您可以使用单个 semantic_text 字段来收集其他字段的值以进行语义搜索。每个值的嵌入是分别计算的;每个字段值在结果嵌入中是单独的一组块。

这给批量请求和更新包含semantic_text字段的文档的摄取管道施加了限制。 在这些情况下,所有复制到semantic_text字段的字段,包括semantic_text字段值,都必须有一个值,以确保每个嵌入都能被正确计算。

例如,以下映射:

PUT test-index
{
    "mappings": {
        "properties": {
            "infer_field": {
                "type": "semantic_text",
                "inference_id": "my-elser-endpoint"
            },
            "source_field": {
                "type": "text",
                "copy_to": "infer_field"
            }
        }
    }
}

需要以下批量更新请求以确保 infer_field 被正确更新:

PUT test-index/_bulk
{"update": {"_id": "1"}}
{"doc": {"infer_field": "updated inference field", "source_field": "updated source field"}}

请注意,在批量请求中,semantic_text 字段和源字段都被更新了。

限制

edit

semantic_text 字段类型有以下限制:

  • semantic_text 字段目前不支持作为 嵌套字段 的元素。
  • semantic_text 字段不能定义为另一个字段的 多字段,也不能包含其他字段作为多字段。

形状字段类型

edit

The shape 数据类型便于对任意 x, y 笛卡尔形状(如矩形和多边形)进行索引和搜索。它可以用于索引和查询坐标落在二维平面坐标系中的几何图形。

您可以使用形状查询来查询此类文档。

映射选项

edit

geo_shape字段类型类似,shape字段映射将 GeoJSONWell-Known Text (WKT)几何对象映射到形状类型。要启用它,用户必须显式地将字段映射到形状类型。

Option Description Default

方向

可选地定义如何解释多边形/多边形的顶点顺序。此参数定义了两种坐标系规则(右手或左手)中的一种,每种规则可以通过三种不同的方式指定。1. 右手规则:rightccwcounterclockwise,2. 左手规则:leftcwclockwise。默认方向(counterclockwise)符合OGC标准,该标准定义外环顶点为逆时针顺序,内环顶点(孔)为顺时针顺序。在geo_shape映射中设置此参数会显式设置geo_shape字段的坐标列表的顶点顺序,但可以在每个单独的GeoJSON或WKT文档中被覆盖。

ccw

ignore_malformed

如果为真,格式错误的GeoJSON或WKT形状将被忽略。如果为假(默认),格式错误的GeoJSON和WKT形状将抛出异常并拒绝整个文档。

ignore_z_value

如果为true(默认),将接受三维点(存储在源中),但仅索引纬度和经度值;第三维度被忽略。如果为false,则包含超过纬度和经度(二维)值的地理点将抛出异常并拒绝整个文档。

coerce

如果 true,多边形中未闭合的线性环将自动闭合。

索引方法

edit

geo_shape类似,shape字段类型通过将几何图形分解为三角网格,并将每个三角形索引为BKD树中的一个7维点来进行索引。 提供给索引器的坐标是单精度浮点值,因此该字段保证了与Java虚拟机提供的相同的精度(通常为1E-38)。对于多边形/多重多边形,镶嵌器的性能主要取决于定义几何图形的顶点数量。

重要提示

CONTAINS 关系查询 - 使用 contains 定义的 relationshape 查询在 ElasticSearch 7.5.0 或更高版本创建的索引中受支持。

示例
edit
PUT /example
{
  "mappings": {
    "properties": {
      "geometry": {
        "type": "shape"
      }
    }
  }
}

此映射定义将几何字段映射到形状类型。索引器使用单精度浮点数来表示顶点值,因此精度与Java虚拟机提供的float值的精度大致相同(通常为1E-38)。

输入结构

edit

形状可以使用GeoJSON熟知文本 (WKT)格式表示。下表提供了GeoJSON和WKT到Elasticsearch类型的映射:

GeoJSON Type WKT Type Elasticsearch Type Description

一个单一的x, y坐标。

LineString

LINESTRING

linestring

给定两个或更多点的一条任意线。

多边形

多边形

多边形

一个闭合的多边形,其第一个和最后一个点必须匹配,因此需要n + 1个顶点来创建一个n边形,并且最少需要4个顶点。

多点

多点

多点

一组未连接但可能相关的点。

多线串

MULTILINESTRING

多线串

一组独立的线串。

多边形集合

MULTIPOLYGON

多边形集合

一个由多个独立多边形组成的数组。

GeometryCollection

GEOMETRYCOLLECTION

几何集合

一个形状集合,类似于multi*形状,但允许多种类型共存(例如,一个点和一条线串)。

N/A

BBOX

信封

一个边界矩形,或信封,通过仅指定左上角和右下角点来指定。

对于所有类型,都需要同时包含内部字段typecoordinates

在GeoJSON和WKT中,以及因此Elasticsearch中,坐标数组内的正确坐标顺序是(X, Y)。这与许多地理空间API(例如,geo_shape)通常使用的俗称纬度、经度(Y, X)顺序不同。

点是笛卡尔坐标系中的一个单一坐标 x, y。它可能代表虚拟世界或投影空间中某个感兴趣项目的位置。以下是GeoJSON中一个点的示例。

POST /example/_doc
{
  "location" : {
    "type" : "point",
    "coordinates" : [-377.03653, 389.897676]
  }
}

以下是一个WKT中点的示例:

POST /example/_doc
{
  "location" : "POINT (-377.03653 389.897676)"
}

由两个或更多位置的数组定义的linestring。通过仅指定两个点,linestring将表示一条直线。指定两个以上的点将创建任意路径。以下是GeoJSON中LineString的一个示例。

POST /example/_doc
{
  "location" : {
    "type" : "linestring",
    "coordinates" : [[-377.03653, 389.897676], [-377.009051, 389.889939]]
  }
}

以下是WKT中LineString的一个示例:

POST /example/_doc
{
  "location" : "LINESTRING (-377.03653 389.897676, -377.009051 389.889939)"
}

多边形由一系列点列表定义。每个(外部)列表中的第一个和最后一个点必须是相同的(多边形必须是封闭的)。以下是GeoJSON中多边形的一个示例。

POST /example/_doc
{
  "location" : {
    "type" : "polygon",
    "coordinates" : [
      [ [1000.0, -1001.0], [1001.0, -1001.0], [1001.0, -1000.0], [1000.0, -1000.0], [1000.0, -1001.0] ]
    ]
  }
}

以下是WKT中多边形的一个示例:

POST /example/_doc
{
  "location" : "POLYGON ((1000.0 -1001.0, 1001.0 -1001.0, 1001.0 -1000.0, 1000.0 -1000.0, 1000.0 -1001.0))"
}

第一个数组表示多边形的外边界,其他数组表示内部形状(“孔”)。以下是一个带有孔的多边形的GeoJSON示例:

POST /example/_doc
{
  "location" : {
    "type" : "polygon",
    "coordinates" : [
      [ [1000.0, -1001.0], [1001.0, -1001.0], [1001.0, -1000.0], [1000.0, -1000.0], [1000.0, -1001.0] ],
      [ [1000.2, -1001.2], [1000.8, -1001.2], [1000.8, -1001.8], [1000.2, -1001.8], [1000.2, -1001.2] ]
    ]
  }
}

以下是一个带有孔洞的多边形的WKT示例:

POST /example/_doc
{
  "location" : "POLYGON ((1000.0 1000.0, 1001.0 1000.0, 1001.0 1001.0, 1000.0 1001.0, 1000.0 1000.0), (1000.2 1000.2, 1000.8 1000.2, 1000.8 1000.8, 1000.2 1000.8, 1000.2 1000.2))"
}

重要提示: WKT 不强制规定顶点的特定顺序。 GeoJSON 规定外多边形必须是逆时针方向,内部形状必须是顺时针方向, 这与开放地理空间联盟(OGC) 简单要素访问 规范中关于顶点顺序的规定一致。

默认情况下,Elasticsearch 期望顶点按逆时针(右手定则)顺序排列。如果数据按顺时针顺序(左手定则)提供,用户可以在字段映射中或作为文档提供的参数中更改 orientation 参数。

以下是一个覆盖文档中orientation参数的示例:

POST /example/_doc
{
  "location" : {
    "type" : "polygon",
    "orientation" : "clockwise",
    "coordinates" : [
      [ [1000.0, 1000.0], [1000.0, 1001.0], [1001.0, 1001.0], [1001.0, 1000.0], [1000.0, 1000.0] ]
    ]
  }
}

以下是GeoJSON点列表的一个示例:

POST /example/_doc
{
  "location" : {
    "type" : "multipoint",
    "coordinates" : [
      [1002.0, 1002.0], [1003.0, 2000.0]
    ]
  }
}

以下是一个WKT点列表的示例:

POST /example/_doc
{
  "location" : "MULTIPOINT (1002.0 2000.0, 1003.0 2000.0)"
}

以下是一个GeoJSON线串列表的示例:

POST /example/_doc
{
  "location" : {
    "type" : "multilinestring",
    "coordinates" : [
      [ [1002.0, 200.0], [1003.0, 200.0], [1003.0, 300.0], [1002.0, 300.0] ],
      [ [1000.0, 100.0], [1001.0, 100.0], [1001.0, 100.0], [1000.0, 100.0] ],
      [ [1000.2, 100.2], [1000.8, 100.2], [1000.8, 100.8], [1000.2, 100.8] ]
    ]
  }
}

以下是WKT线串列表的一个示例:

POST /example/_doc
{
  "location" : "MULTILINESTRING ((1002.0 200.0, 1003.0 200.0, 1003.0 300.0, 1002.0 300.0), (1000.0 100.0, 1001.0 100.0, 1001.0 100.0, 1000.0 100.0), (1000.2 0.2, 1000.8 100.2, 1000.8 100.8, 1000.2 100.8))"
}

以下是一个包含GeoJSON多边形列表的示例(第二个多边形包含一个洞):

POST /example/_doc
{
  "location" : {
    "type" : "multipolygon",
    "coordinates" : [
      [ [[1002.0, 200.0], [1003.0, 200.0], [1003.0, 300.0], [1002.0, 300.0], [1002.0, 200.0]] ],
      [ [[1000.0, 200.0], [1001.0, 100.0], [1001.0, 100.0], [1000.0, 100.0], [1000.0, 100.0]],
        [[1000.2, 200.2], [1000.8, 100.2], [1000.8, 100.8], [1000.2, 100.8], [1000.2, 100.2]] ]
    ]
  }
}

以下是一个WKT多边形列表的示例(第二个多边形包含一个洞):

POST /example/_doc
{
  "location" : "MULTIPOLYGON (((1002.0 200.0, 1003.0 200.0, 1003.0 300.0, 1002.0 300.0, 102.0 200.0)), ((1000.0 100.0, 1001.0 100.0, 1001.0 100.0, 1000.0 100.0, 1000.0 100.0), (1000.2 100.2, 1000.8 100.2, 1000.8 100.8, 1000.2 100.8, 1000.2 100.2)))"
}

以下是一个包含多个GeoJSON几何对象的示例:

POST /example/_doc
{
  "location" : {
    "type": "geometrycollection",
    "geometries": [
      {
        "type": "point",
        "coordinates": [1000.0, 100.0]
      },
      {
        "type": "linestring",
        "coordinates": [ [1001.0, 100.0], [1002.0, 100.0] ]
      }
    ]
  }
}

以下是一个WKT几何对象集合的示例:

POST /example/_doc
{
  "location" : "GEOMETRYCOLLECTION (POINT (1000.0 100.0), LINESTRING (1001.0 100.0, 1002.0 100.0))"
}
信封
edit

Elasticsearch 支持一种 envelope 类型,它由形状的左上角和右下角的坐标组成,以表示边界矩形,格式为 [[minX, maxY], [maxX, minY]]

POST /example/_doc
{
  "location" : {
    "type" : "envelope",
    "coordinates" : [ [1000.0, 100.0], [1001.0, 100.0] ]
  }
}

以下是使用WKT BBOX格式的信封示例:

注意: WKT 规范要求以下顺序:minLon, maxLon, maxLat, minLat。

POST /example/_doc
{
  "location" : "BBOX (1000.0, 1002.0, 2000.0, 1000.0)"
}

排序和检索索引形状

edit

由于形状的复杂输入结构和索引表示,目前无法直接对形状进行排序或检索其字段。shape 值只能通过 _source 字段检索。

稀疏向量场类型

edit

一个 sparse_vector 字段可以索引特征和权重,以便在带有 sparse_vector 的查询中用于查询文档。 该字段还可以与遗留的 text_expansion 查询一起使用。

sparse_vector 是应与 ELSER 映射 一起使用的字段类型。

PUT my-index
{
  "mappings": {
    "properties": {
      "text.tokens": {
        "type": "sparse_vector"
      }
    }
  }
}

请参阅使用ELSER进行语义搜索,了解如何使用ELSER向sparse_vector映射字段添加文档的完整示例。

多值稀疏向量

edit

当为稀疏向量传入值数组时,会选择名称相似的特征的最大值。

论文《Adapting Learned Sparse Retrieval for Long Documents》(https://arxiv.org/pdf/2305.18494.pdf)对此进行了更详细的讨论。 总之,研究结果表明,表示聚合通常优于分数聚合。

在需要使用重叠特征名称的情况下,应将它们分别存储或使用嵌套字段。

下面是一个传递具有重叠特征名称的文档的示例。 考虑在这个示例中,存在两个类别用于正面情感和负面情感。 然而,为了检索的目的,我们还需要整体影响,而不是特定的情感。 在示例中,impact 存储为一个多值稀疏向量,并且只存储重叠名称的最大值。 更具体地说,这里的最终 GET 查询返回一个 _score 约为 1.2(即 max(impact.delicious[0], impact.delicious[1]),由于我们有一个相对误差为 0.4%,因此是近似的,如下所述)

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "text": {
        "type": "text",
        "analyzer": "standard"
      },
      "impact": {
        "type": "sparse_vector"
      },
      "positive": {
        "type": "sparse_vector"
      },
      "negative": {
        "type": "sparse_vector"
      }
    }
  }
}

POST my-index-000001/_doc
{
    "text": "I had some terribly delicious carrots.",
    "impact": [{"I": 0.55, "had": 0.4, "some": 0.28, "terribly": 0.01, "delicious": 1.2, "carrots": 0.8},
               {"I": 0.54, "had": 0.4, "some": 0.28, "terribly": 2.01, "delicious": 0.02, "carrots": 0.4}],
    "positive": {"I": 0.55, "had": 0.4, "some": 0.28, "terribly": 0.01, "delicious": 1.2, "carrots": 0.8},
    "negative": {"I": 0.54, "had": 0.4, "some": 0.28, "terribly": 2.01, "delicious": 0.02, "carrots": 0.4}
}

GET my-index-000001/_search
{
  "query": {
    "term": {
      "impact": {
         "value": "delicious"
      }
    }
  }
}

sparse_vector 字段不能包含在 Elasticsearch 版本 8.0 到 8.10 之间创建的索引中

sparse_vector 字段仅支持严格正值。 负值将被拒绝。

sparse_vector 字段不支持 分析器、查询、排序或聚合。 它们只能用于专门的查询中。 在这些字段上推荐的查询是 sparse_vector 查询。 它们也可以用于遗留的 text_expansion 查询中。

sparse_vector 字段仅保留9位有效位用于精度,这相当于大约0.4%的相对误差。

文本类型家族

edit

文本系列包括以下字段类型:

  • text,传统的字段类型,用于全文内容,例如电子邮件的正文或产品的描述。
  • match_only_texttext的空间优化变体,禁用评分并在需要位置的查询上执行较慢。它最适合用于索引日志消息。

文本字段类型

edit

用于索引全文值的字段,例如电子邮件的正文或产品的描述。这些字段是分析过的,也就是说,它们在索引之前通过一个分析器被转换为单个术语的列表。分析过程允许Elasticsearch在每个全文字段中搜索单个单词。文本字段不用于排序,也很少用于聚合(尽管显著文本聚合是一个值得注意的例外)。

text 字段最适合用于非结构化但人类可读的内容。如果您需要索引非结构化的机器生成内容,请参阅 映射非结构化内容

如果你需要索引结构化内容,如电子邮件地址、主机名、状态码或标签,那么你可能应该使用一个keyword字段。

下面是一个文本字段映射的示例:

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "full_name": {
        "type":  "text"
      }
    }
  }
}

将字段同时用作文本和关键词

edit

有时,同时拥有同一字段的完整文本版本(text)和关键词版本(keyword)会很有用:一个用于全文搜索,另一个用于聚合和排序。这可以通过多字段来实现。

文本字段的参数

edit

以下参数被text字段接受:

analyzer

用于text字段的分析器,在索引时和搜索时都应使用(除非被search_analyzer覆盖)。默认值为默认索引分析器,或standard分析器

eager_global_ordinals

是否应在刷新时急切加载全局序数?接受 truefalse(默认)。在经常用于(重要)词条聚合的字段上启用此功能是一个好主意。

fielddata

该字段是否可以使用内存中的fielddata进行排序、聚合或脚本操作?接受truefalse(默认)。

fielddata_frequency_filter

专家设置,允许在启用 fielddata 时决定加载哪些值到内存中。默认情况下,所有值都会被加载。

fields

多字段允许将相同的字符串值以多种方式进行索引,以满足不同的目的,例如一个字段用于搜索,另一个多字段用于排序和聚合,或者使用不同的分析器对相同的字符串值进行分析。

index

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

index_options

为了搜索和突出显示的目的,索引中应存储哪些信息。 默认为 positions

index_prefixes

如果启用,长度在2到5个字符之间的术语前缀将被索引到一个单独的字段中。这使得前缀搜索能够更高效地运行,但代价是索引更大。

index_phrases

如果启用,双词组合(shingles)将被索引到一个单独的字段中。这使得精确短语查询(无偏差)能够更高效地运行,但代价是索引更大。请注意,当停用词未被移除时,此功能效果最佳,因为包含停用词的短语将不会使用辅助字段,而是回退到标准短语查询。接受 truefalse(默认)。

norms

是否应在评分查询时考虑字段长度。 接受 true(默认)或 false

position_increment_gap

在字符串数组中的每个元素之间应插入的假词位置的数量。默认为分析器上配置的position_increment_gap,其默认值为100。选择100是因为它可以防止带有合理大跨度(小于100)的短语查询匹配跨字段值的词项。

store

字段值是否应与_source字段分开存储和检索。接受truefalse(默认)。

search_analyzer

在搜索时应使用的分析器文本字段上。默认为分析器设置。

search_quote_analyzer

在搜索时遇到短语时应使用的分析器。默认为search_analyzer设置。

similarity

使用哪种评分算法或相似度。默认为BM25

term_vector

是否应为该字段存储词向量。默认为

meta

字段的元数据。

合成 _source

edit

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

text 字段支持 synthetic _source,如果它们有一个支持 synthetic _sourcekeyword 子字段,或者如果 text 字段将 store 设置为 true。无论哪种方式,它可能没有 copy_to

如果使用子keyword字段,则值的排序方式与keyword字段的值排序方式相同。默认情况下,这意味着排序时会去除重复项。因此:

PUT idx
{
  "settings": {
    "index": {
      "mapping": {
        "source": {
          "mode": "synthetic"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "text": {
        "type": "text",
        "fields": {
          "raw": {
            "type": "keyword"
          }
        }
      }
    }
  }
}
PUT idx/_doc/1
{
  "text": [
    "the quick brown fox",
    "the quick brown fox",
    "jumped over the lazy dog"
  ]
}

将变为:

{
  "text": [
    "jumped over the lazy dog",
    "the quick brown fox"
  ]
}

重新排序文本字段可能会影响短语跨度查询。有关更多详细信息,请参阅关于 position_increment_gap的讨论。您 可以通过确保短语查询中的slop参数 低于position_increment_gap来避免这种情况。这是默认设置。

如果 text 字段将 store 设置为 true,则顺序和重复项将被保留。

PUT idx
{
  "settings": {
    "index": {
      "mapping": {
        "source": {
          "mode": "synthetic"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "text": { "type": "text", "store": true }
    }
  }
}
PUT idx/_doc/1
{
  "text": [
    "the quick brown fox",
    "the quick brown fox",
    "jumped over the lazy dog"
  ]
}

将变为:

{
  "text": [
    "the quick brown fox",
    "the quick brown fox",
    "jumped over the lazy dog"
  ]
}

fielddata 映射参数

edit

text 字段默认是可搜索的,但默认情况下不可用于聚合、排序或脚本。如果你尝试对 text 字段进行排序、聚合或使用脚本访问其值,你会看到一个异常,指示默认情况下在文本字段上禁用了字段数据。要在内存中加载字段数据,请在你的字段上设置 fielddata=true

在内存中加载字段数据可能会消耗大量内存。

字段数据是访问全文字段中分析后的标记以进行聚合、排序或脚本的唯一方式。例如,一个全文字段如New York会被分析为newyork。要对这些标记进行聚合,需要字段数据。

启用fielddata前的注意事项

edit

通常情况下,在文本字段上启用fielddata是没有意义的。Field data存储在堆内存中,使用field data缓存,因为计算它是非常昂贵的。计算field data可能会导致延迟峰值,并且增加堆内存使用是集群性能问题的一个原因。

大多数想要对文本字段进行更多操作的用户会使用多字段映射, 通过同时拥有一个用于全文搜索的text字段,以及一个 未分析的用于聚合的keyword字段,如下所示:

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "my_field": { 
        "type": "text",
        "fields": {
          "keyword": { 
            "type": "keyword"
          }
        }
      }
    }
  }
}

使用 my_field 字段进行搜索。

使用 my_field.keyword 字段进行聚合、排序或在脚本中使用。

text字段上启用fielddata

edit

您可以使用更新映射 API在现有的text字段上启用fielddata,如下所示:

PUT my-index-000001/_mapping
{
  "properties": {
    "my_field": { 
      "type":     "text",
      "fielddata": true
    }
  }
}

您为 my_field 指定的映射应包括该字段的现有映射,以及 fielddata 参数。

fielddata_frequency_filter 映射参数

edit

字段数据过滤可以用于减少加载到内存中的词项数量,从而减少内存使用。词项可以通过频率进行过滤:

频率过滤器允许你只加载文档频率落在minmax值之间的术语,这可以表示为绝对数(当数字大于1.0时)或百分比(例如0.011%1.0100%)。频率是按每个分段计算的。百分比基于具有该字段值的文档数量,而不是分段中的所有文档。

可以通过指定段落应包含的最小文档数量来完全排除小段落,使用 min_segment_size

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "tag": {
        "type": "text",
        "fielddata": true,
        "fielddata_frequency_filter": {
          "min": 0.001,
          "max": 0.1,
          "min_segment_size": 500
        }
      }
    }
  }
}

仅匹配文本字段类型

edit

一种text的变体,它在空间效率上进行了权衡,牺牲了评分和位置查询的效率。该字段实际上以与仅索引文档的text字段(index_options: docs)并禁用规范(norms: false)相同的方式存储数据。术语查询的执行速度与text字段一样快,甚至更快,然而需要位置的查询,如match_phrase查询,执行速度较慢,因为它们需要查看_source文档以验证短语是否匹配。所有查询返回的常量分数等于1.0。

分析是不可配置的:文本总是使用默认分析器进行分析(默认情况下为standard)。

跨度查询在此字段中不受支持,请改用区间查询,或者如果您绝对需要跨度查询,请使用text字段类型。

除此之外,match_only_text 支持与 text 相同的查询。并且与 text 一样,它不支持排序,并且仅对聚合提供有限的支持。

PUT logs
{
  "mappings": {
    "properties": {
      "@timestamp": {
        "type": "date"
      },
      "message": {
        "type": "match_only_text"
      }
    }
  }
}

仅匹配文本字段的参数

edit

接受的映射参数如下:

fields

多字段允许将相同的字符串值以多种方式进行索引,以满足不同的目的,例如一个字段用于搜索,而另一个多字段用于排序和聚合,或者使用不同的分析器对相同的字符串值进行分析。

meta

字段的元数据。

Token 计数字段类型

edit

类型为 token_count 的字段实际上是一个 integer 字段,它接受字符串值,对其进行分析,然后索引字符串中的标记数量。

例如:

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "name": { 
        "type": "text",
        "fields": {
          "length": { 
            "type":     "token_count",
            "analyzer": "standard"
          }
        }
      }
    }
  }
}

PUT my-index-000001/_doc/1
{ "name": "John Smith" }

PUT my-index-000001/_doc/2
{ "name": "Rachel Alice Williams" }

GET my-index-000001/_search
{
  "query": {
    "term": {
      "name.length": 3 
    }
  }
}

字段 name 是一个使用默认 standard 分析器的 text 字段。

字段 name.length 是一个 token_count 多字段,它将索引 name 字段中的标记数量。

此查询仅匹配包含 Rachel Alice Williams 的文档,因为它包含三个词项。

token_count 字段的参数

edit

以下参数被token_count字段接受:

analyzer

用于分析字符串值的分析器。必需。为了获得最佳性能,请使用不带标记过滤器的分析器。

enable_position_increments

指示是否应计算位置增量。 如果不想计算由分析器过滤器(如stop)移除的标记,请设置为false。 默认为true

doc_values

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

index

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

null_value

接受与字段相同类型的数值,该数值将替换任何显式的null值。默认为null,这意味着该字段被视为缺失。

store

字段值是否应与_source字段分开存储和检索。接受truefalse(默认)。

合成 _source

edit

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

token_count 字段在其默认配置中支持 synthetic _source

无符号长字段类型

edit

无符号长整型是一种数值字段类型,表示一个无符号的64位整数,其最小值为0,最大值为264-1(从0到18446744073709551615,包含两端)。

PUT my_index
{
  "mappings": {
    "properties": {
      "my_counter": {
        "type": "unsigned_long"
      }
    }
  }
}

无符号长整型可以以数字或字符串形式进行索引, 表示范围在 [0, 18446744073709551615] 内的整数值。 它们不能有小数部分。

POST /my_index/_bulk?refresh
{"index":{"_id":1}}
{"my_counter": 0}
{"index":{"_id":2}}
{"my_counter": 9223372036854775808}
{"index":{"_id":3}}
{"my_counter": 18446744073709551614}
{"index":{"_id":4}}
{"my_counter": 18446744073709551615}

术语查询接受任何数字形式或字符串形式的数字。

GET /my_index/_search
{
    "query": {
        "term" : {
            "my_counter" : 18446744073709551615
        }
    }
}

范围查询条件可以包含带有小数部分的值。 在这种情况下,Elasticsearch 会将它们转换为整数值: gtegt 条件会向上取整,包含边界值, 而 ltlte 范围会向下取整,包含边界值。

建议将范围作为字符串传递,以确保它们在解析时不会丢失任何精度。

GET /my_index/_search
{
    "query": {
        "range" : {
            "my_counter" : {
                "gte" : "9223372036854775808",
                "lte" : "18446744073709551615"
            }
        }
    }
}

排序值

edit

对于在unsigned_long字段上进行排序的查询, 对于特定文档,如果该文档的值在long值范围内,Elasticsearch会返回类型为long的排序值, 如果该值超出此范围,则返回类型为BigInteger的排序值。

REST客户端需要能够处理JSON中的大整数值,以正确支持此字段类型。

GET /my_index/_search
{
    "query": {
        "match_all" : {}
    },
    "sort" : {"my_counter" : "desc"}
}

存储字段

edit

一个存储的字段 unsigned_long 被存储并以 String 形式返回。

聚合

edit

对于terms聚合,类似于排序值,使用LongBigInteger值。对于其他聚合,值被转换为double类型。

脚本值

edit

默认情况下,unsigned_long 字段的脚本值会以 Java 有符号 Long 的形式返回,这意味着大于 Long.MAX_VALUE 的值会显示为负值。您可以使用 Long.compareUnsigned(long, long)Long.divideUnsigned(long, long)Long.remainderUnsigned(long, long) 来正确处理这些值。

例如,下面的脚本返回计数器除以10的值。

GET /my_index/_search
{
    "query": {
        "match_all" : {}
    },
    "script_fields": {
        "count10" : {
          "script": {
            "source": "Long.divideUnsigned(doc['my_counter'].value, 10)"
          }
        }
    }
}

或者,您可以通过使用字段 API 将无符号长整型视为 BigInteger 在您的脚本中。例如,此脚本 将 my_counter 视为 BigInteger,默认值为 BigInteger.ZERO

"script": {
    "source": "field('my_counter').asBigInteger(BigInteger.ZERO)"
}

对于需要返回浮点数或双精度数值的脚本,您可以将BigInteger值进一步转换为双精度或浮点数:

GET /my_index/_search
{
    "query": {
        "script_score": {
          "query": {"match_all": {}},
          "script": {
            "source": "field('my_counter').asBigInteger(BigInteger.ZERO).floatValue()"
          }
        }
    }
}

混合数值类型的查询

edit

支持混合数值类型的搜索,其中一种是unsigned_long,但不支持带有排序的查询。因此,在两个索引中对同一字段名称进行排序查询,其中一个索引中的字段类型为unsigned_long,另一个索引中的字段类型为long,不会产生正确的结果,必须避免这种情况。如果需要进行此类排序,可以使用基于脚本的排序来代替。

支持对几种数值类型进行聚合,其中一种是unsigned_long。在这种情况下,值会被转换为double类型。

版本字段类型

edit

version 字段类型是 keyword 字段的一个专门化,用于处理软件版本值并支持它们的专用优先规则。优先级是根据 语义版本控制 的规则定义的,这意味着主要、次要和补丁版本部分按数值排序(例如 "2.1.0" < "2.4.1" < "2.11.2"),并且预发布版本在发布版本之前排序(例如 "1.0.0-alpha" < "1.0.0")。

您可以如下索引一个version字段

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "my_version": {
        "type": "version"
      }
    }
  }
}

该字段提供了与常规关键词字段相同的搜索功能。例如,可以使用 matchterm 查询进行精确匹配搜索,并支持前缀和通配符搜索。主要的好处是 range 查询将遵循语义版本排序,因此介于 "1.0.0" 和 "1.5.0" 之间的 range 查询将包括 "1.2.3" 版本,但不包括 "1.11.2" 版本。请注意,如果使用常规的 keyword 字段进行索引,排序将是按字母顺序排列的,结果会有所不同。

软件版本应遵循 语义版本控制规则 的架构和优先规则,但值得注意的是,允许使用多于或少于三个主要版本标识符(即“1.2”或“1.2.3.4”在严格的语义版本控制规则下不符合要求,但在此处被视为有效版本)。不符合语义版本定义的版本字符串(例如“1.2.alpha.4”)仍然可以被索引和作为精确匹配检索,但它们将按照常规字母顺序出现在所有有效版本之后。空字符串“”被视为无效,并排在所有有效版本之后,但在其他无效版本之前。

版本字段的参数

edit

以下参数被version字段接受:

meta

字段的元数据。

限制

edit

这种字段类型并不针对大量的通配符、正则表达式或模糊搜索进行优化。虽然这些类型的查询在此字段中可以工作,但如果您强烈依赖这些类型的查询,您应该考虑使用一个常规的 keyword 字段。

合成 _source

edit

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

version 字段在其默认配置中支持 synthetic _source

合成源可能会对version字段值进行排序并去除重复项。例如:

PUT idx
{
  "settings": {
    "index": {
      "mapping": {
        "source": {
          "mode": "synthetic"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "versions": { "type": "version" }
    }
  }
}
PUT idx/_doc/1
{
  "versions": ["8.0.0-beta1", "8.5.0", "0.90.12", "2.6.1", "1.3.4", "1.3.4"]
}

将变为:

{
  "versions": ["0.90.12", "1.3.4", "2.6.1", "8.0.0-beta1", "8.5.0"]
}