首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >elasticsearch中Flattened字段的介绍

elasticsearch中Flattened字段的介绍

原创
作者头像
保持热爱奔赴山海
发布于 2025-06-14 07:22:30
发布于 2025-06-14 07:22:30
1420
举报
文章被收录于专栏:数据库相关数据库相关

从ES7.3开始,引入了 Flattened  这种field类型。

Flattened 数据类型对于索引具有大量或未知数量的唯一键的对象很有用。仅为整个 JSON 对象创建一个字段映射,这可以帮助防止由于大量不同的字段映射而导致映射爆炸

此外,Flattened 的对象字段在搜索功能方面存在折衷,例如不支持下面的3种查询:

  • 无法执行涉及数字计算的查询,例如:range query。
  • 无法支持高亮查询。
  • 尽管支持诸如 term 聚合之类的聚合,但不支持处理诸如“histograms”或“date_histograms”之类的数值数据的聚合。

在使用 flattened 数据类型时,必须注意的是:

flattened 的映射类型不应用于索引所有文档内容,因为它将所有值都视为关键字,并且不提供完整的搜索功能。 在大多数情况下,默认方法(每个子字段在映射中都有其自己相对应的项)有效。

下面内容来自官方文档的翻译。

默认情况下,对象中的每个子字段都是单独映射和索引的。如果事先不知道子字段的名称或类型,则会动态映射。

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

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

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

注意:

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

代码语言:txt
AI代码解释
复制
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
    }
  }
}

GET bug_reports/_mapping
{
  "bug_reports": {
    "mappings": {
      "properties": {
        "labels": {
          "type": "flattened"
        },
        "title": {
          "type": "text"
        }
      }
    }
  }
}

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

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

代码语言:txt
AI代码解释
复制
POST bug_reports/_search
{
  "query": {
    "term": {"labels": "urgent"}
  }
}

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

代码语言:txt
AI代码解释
复制
POST bug_reports/_search
{
  "query": {
    "term": {"labels.release": "v1.3.0"}
  }
}

支持的运算

目前,扁平化对象字段可以与以下查询类型一起使用:

代码语言:txt
AI代码解释
复制
term, terms, and terms_set
prefix
range
 match 和 multi_match
query_string 和 simple_query_string
exists

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

可以在扁平化对象字段上排序,同时也可以执行简单的关键词式聚合,例如 terms 。与查询一样,没有对数值的特殊支持——JSON 对象中的所有值都按关键词处理。在排序时,这意味着值将按字典顺序进行比较。

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

检索扁平化字段

字段值和具体子字段可以通过 fields 参数获取。由于 flattened 字段将整个对象(可能包含许多子字段)映射为单个字段,响应包含来自 _source 的未修改结构。

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

代码语言:txt
AI代码解释
复制
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['<field_name>'].value ,而是使用 doc['<field_name>.<sub-field_name>'].value 。例如,如果你有一个名为 label 的扁平化字段,其中包含一个 release 子字段,你的 Painless 脚本将是 doc['labels.release'].value

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

代码语言:txt
AI代码解释
复制
PUT my-index-000001
{
  "mappings": {
    "properties": {
      "title": {
        "type": "text"
      },
      "labels": {
        "type": "flattened"
      }
    }
  }
}

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

代码语言:txt
AI代码解释
复制
POST my-index-000001/_doc/1
{
  "title": "Something really urgent",
  "labels": {
    "priority": "urgent",
    "release": [
      "v1.2.5",
      "v1.3.0"
    ],
    "timestamp": {
      "created": 1541458026,
      "closed": 1541457010
    }
  }
}

POST /my-index-000001/_doc/2
{
  "title": "Somewhat less urgent",
  "labels": {
    "priority": "high",
    "release": [
      "v1.3.0"
    ],
    "timestamp": {
      "created": 1541458026,
      "closed": 1541457010
    }
  }
}

POST /my-index-000001/_doc/3
{
  "title": "Not urgent",
  "labels": {
    "priority": "low",
    "release": [
      "v1.2.0"
    ],
    "timestamp": {
      "created": 1541458026,
      "closed": 1541457010
    }
  }
}

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

代码语言:txt
AI代码解释
复制
"script": {
  "source": """
    if (doc['labels.release'].value.equals('v1.3.0'))
    {emit(doc['labels.release'].value)}
    else{emit('Version mismatch')}
  """

官方文档: https://www.elastic.co/guide/en/elasticsearch/reference/8.18/flattened.html

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档