关键字类型家族编辑

关键字家族包括以下字段类型

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

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

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

关键字字段类型编辑

以下是基本 keyword 字段的映射示例

resp = client.indices.create(
    index="my-index-000001",
    body={"mappings": {"properties": {"tags": {"type": "keyword"}}}},
)
print(resp)
response = client.indices.create(
  index: 'my-index-000001',
  body: {
    mappings: {
      properties: {
        tags: {
          type: 'keyword'
        }
      }
    }
  }
)
puts response
res, err := es.Indices.Create(
	"my-index-000001",
	es.Indices.Create.WithBody(strings.NewReader(`{
	  "mappings": {
	    "properties": {
	      "tags": {
	        "type": "keyword"
	      }
	    }
	  }
	}`)),
)
fmt.Println(res, err)
PUT my-index-000001
{
  "mappings": {
    "properties": {
      "tags": {
        "type":  "keyword"
      }
    }
  }
}

映射数字标识符

并非所有数字数据都应映射为 数字 字段数据类型。Elasticsearch 优化了数字字段(例如 integerlong),用于 range 查询。但是,keyword 字段更适合 term 和其他 词条级 查询。

标识符(例如 ISBN 或产品 ID)很少用于 range 查询中。但是,它们通常使用词条级查询检索。

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

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

如果您不确定使用哪个,可以使用 多字段 将数据同时映射为 keyword *和* 数字数据类型。

基本关键字字段的参数编辑

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 索引设置限制了索引中的维度数量。

维度字段具有以下约束

  • doc_valuesindex 映射参数必须为 true
  • 字段值不能是 数组或多值
  • 维度值用于标识文档的时间序列。如果在索引过程中以任何方式更改了维度值,则该文档将被存储为属于与预期不同的时间序列。因此,还有一些额外的约束

合成 _source编辑

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

keyword 字段在其默认配置中支持 合成 _source。合成 _source 不能与 normalizercopy_to 一起使用。

默认情况下,合成源会对 keyword 字段进行排序并删除重复项。例如

resp = client.indices.create(
    index="idx",
    body={
        "mappings": {
            "_source": {"mode": "synthetic"},
            "properties": {"kwd": {"type": "keyword"}},
        }
    },
)
print(resp)

resp = client.index(
    index="idx",
    id="1",
    body={"kwd": ["foo", "foo", "bar", "baz"]},
)
print(resp)
response = client.indices.create(
  index: 'idx',
  body: {
    mappings: {
      _source: {
        mode: 'synthetic'
      },
      properties: {
        kwd: {
          type: 'keyword'
        }
      }
    }
  }
)
puts response

response = client.index(
  index: 'idx',
  id: 1,
  body: {
    kwd: [
      'foo',
      'foo',
      'bar',
      'baz'
    ]
  }
)
puts response
PUT idx
{
  "mappings": {
    "_source": { "mode": "synthetic" },
    "properties": {
      "kwd": { "type": "keyword" }
    }
  }
}
PUT idx/_doc/1
{
  "kwd": ["foo", "foo", "bar", "baz"]
}

将变为

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

如果 keyword 字段将 store 设置为 true,则会保留顺序和重复项。例如

resp = client.indices.create(
    index="idx",
    body={
        "mappings": {
            "_source": {"mode": "synthetic"},
            "properties": {"kwd": {"type": "keyword", "store": True}},
        }
    },
)
print(resp)

resp = client.index(
    index="idx",
    id="1",
    body={"kwd": ["foo", "foo", "bar", "baz"]},
)
print(resp)
response = client.indices.create(
  index: 'idx',
  body: {
    mappings: {
      _source: {
        mode: 'synthetic'
      },
      properties: {
        kwd: {
          type: 'keyword',
          store: true
        }
      }
    }
  }
)
puts response

response = client.index(
  index: 'idx',
  id: 1,
  body: {
    kwd: [
      'foo',
      'foo',
      'bar',
      'baz'
    ]
  }
)
puts response
PUT idx
{
  "mappings": {
    "_source": { "mode": "synthetic" },
    "properties": {
      "kwd": { "type": "keyword", "store": true }
    }
  }
}
PUT idx/_doc/1
{
  "kwd": ["foo", "foo", "bar", "baz"]
}

将变为

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

长度超过 ignore_above 的值将被保留,但排序到最后。例如

resp = client.indices.create(
    index="idx",
    body={
        "mappings": {
            "_source": {"mode": "synthetic"},
            "properties": {"kwd": {"type": "keyword", "ignore_above": 3}},
        }
    },
)
print(resp)

resp = client.index(
    index="idx",
    id="1",
    body={"kwd": ["foo", "foo", "bang", "bar", "baz"]},
)
print(resp)
response = client.indices.create(
  index: 'idx',
  body: {
    mappings: {
      _source: {
        mode: 'synthetic'
      },
      properties: {
        kwd: {
          type: 'keyword',
          ignore_above: 3
        }
      }
    }
  }
)
puts response

response = client.index(
  index: 'idx',
  id: 1,
  body: {
    kwd: [
      'foo',
      'foo',
      'bang',
      'bar',
      'baz'
    ]
  }
)
puts response
PUT idx
{
  "mappings": {
    "_source": { "mode": "synthetic" },
    "properties": {
      "kwd": { "type": "keyword", "ignore_above": 3 }
    }
  }
}
PUT idx/_doc/1
{
  "kwd": ["foo", "foo", "bang", "bar", "baz"]
}

将变为

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

常量关键字字段类型编辑

常量关键字是 keyword 字段的一种特殊形式,适用于索引中的所有文档都具有相同值的情况。

response = client.indices.create(
  index: 'logs-debug',
  body: {
    mappings: {
      properties: {
        "@timestamp": {
          type: 'date'
        },
        message: {
          type: 'text'
        },
        level: {
          type: 'constant_keyword',
          value: 'debug'
        }
      }
    }
  }
)
puts response
PUT logs-debug
{
  "mappings": {
    "properties": {
      "@timestamp": {
        "type": "date"
      },
      "message": {
        "type": "text"
      },
      "level": {
        "type": "constant_keyword",
        "value": "debug"
      }
    }
  }
}

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

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

response = client.index(
  index: 'logs-debug',
  body: {
    date: '2019-12-12',
    message: 'Starting up Elasticsearch',
    level: 'debug'
  }
)
puts response

response = client.index(
  index: 'logs-debug',
  body: {
    date: '2019-12-12',
    message: 'Starting up Elasticsearch'
  }
)
puts response
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 查询。

该字段的 value 在设置后无法更改。

常量关键字字段的参数编辑

接受以下映射参数

meta

有关该字段的元数据。

value

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

通配符字段类型编辑

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

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

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

response = client.indices.create(
  index: 'my-index-000001',
  body: {
    mappings: {
      properties: {
        my_wildcard: {
          type: 'wildcard'
        }
      }
    }
  }
)
puts response

response = client.index(
  index: 'my-index-000001',
  id: 1,
  body: {
    my_wildcard: 'This string can be quite lengthy'
  }
)
puts response

response = client.search(
  index: 'my-index-000001',
  body: {
    query: {
      wildcard: {
        my_wildcard: {
          value: '*quite*lengthy'
        }
      }
    }
  }
)
puts response
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"
      }
    }
  }
}

通配符字段的参数编辑

wildcard 字段接受以下参数:

null_value

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

ignore_above

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

限制编辑

  • wildcard 字段与关键字字段一样未进行分词,因此不支持依赖词位的查询,例如短语查询。
  • 运行 wildcard 查询时,将忽略任何 rewrite 参数。评分始终是恒定分数。

合成 _source编辑

wildcard 字段支持 合成 _source,只要它们没有声明 copy_to

合成源始终对 wildcard 字段进行排序。例如:

response = client.indices.create(
  index: 'idx',
  body: {
    mappings: {
      _source: {
        mode: 'synthetic'
      },
      properties: {
        card: {
          type: 'wildcard'
        }
      }
    }
  }
)
puts response

response = client.index(
  index: 'idx',
  id: 1,
  body: {
    card: [
      'king',
      'ace',
      'ace',
      'jack'
    ]
  }
)
puts response
PUT idx
{
  "mappings": {
    "_source": { "mode": "synthetic" },
    "properties": {
      "card": { "type": "wildcard" }
    }
  }
}
PUT idx/_doc/1
{
  "card": ["king", "ace", "ace", "jack"]
}

将变为

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