扁平对象字段类型

在 UDB-SX 中,您不必在索引文档之前指定映射。如果您不指定映射,UDB-SX 会使用动态映射自动映射文档中的每个字段及其子字段。当您摄入日志等文档时,可能事先并不知道每个字段的子字段名称和类型。在这种情况下,动态映射所有新的子字段可能会迅速导致“映射爆炸”,即不断增长的字段数量可能会降低集群性能。

扁平对象字段类型通过将整个 JSON 对象视为字符串来解决这个问题。JSON 对象内的子字段可以使用标准的点路径表示法访问,但不会为快速查找而建立索引。

点表示法中字段值的最大长度为 224 − 1。

扁平对象字段类型提供以下好处:

  • 高效读取:获取性能类似于关键字字段。

  • 内存效率:将整个复杂的 JSON 对象存储在一个字段中,而不索引其所有子字段,从而减少了索引中的字段数量。

  • 空间效率:UDB-SX 不会为扁平对象中的子字段创建倒排索引,从而节省空间。

  • 迁移兼容性:您可以将数据从支持类似扁平类型的系统迁移到 UDB-SX。

当字段及其子字段主要用于读取,而不作为搜索条件时(因为子字段未被索引),将字段映射为扁平对象是合适的。扁平对象适用于具有大量字段的对象,或者当您事先不知道键的情况。

扁平对象支持带有点路径表示法和不带点路径表示法的精确匹配查询。有关支持的查询类型的完整列表,请参见支持的查询

在文档中搜索嵌套字段的特定值可能效率低下,因为这可能需要全索引扫描,而这是一项昂贵的操作。

扁平对象不支持:

  • 类型特定的解析。

  • 数值操作,例如数值比较或数值排序。

  • 文本分析。

  • 高亮显示。

  • 使用点表示法对子字段进行聚合。

  • 通过子字段进行过滤。

支持的查询

扁平对象字段类型支持以下查询:

  • 词条查询

  • 多词条查询

  • 词条集查询

  • 前缀查询

  • 范围查询

  • 匹配查询

  • 多字段匹配查询

  • 查询字符串查询

  • 简单查询字符串查询

  • 存在查询

  • 通配符查询

限制

以下限制适用于 UDB-SX 中的扁平对象:

  • 扁平对象不支持开放参数。

  • 用于检索子字段值的 Painless 脚本和通配符查询不受支持。

此功能计划在未来的版本中提供。

使用扁平对象

以下示例说明了如何将字段映射为扁平对象,索引包含扁平对象字段的文档,以及在这些文档中搜索扁平对象的叶值。

首先,为您的索引创建映射,其中 issue 的类型为 flat_object

PUT /test-index/
{
  "mappings": {
    "properties": {
      "issue": {
        "type": "flat_object"
      }
    }
  }
}

接下来,索引两个包含扁平对象字段的文档:

PUT /test-index/_doc/1
{
  "issue": {
    "number": "123456",
    "labels": {
      "version": "2.1",
      "backport": [
        "2.0",
        "1.3"
      ],
      "category": {
        "type": "API",
        "level": "enhancement"
      }
    }
  }
}
PUT /test-index/_doc/2
{
  "issue": {
    "number": "123457",
    "labels": {
      "version": "2.2",
      "category": {
        "type": "API",
        "level": "bug"
      }
    }
  }
}

要搜索扁平对象的叶值,可以使用 GET 或 POST 请求。即使您不知道字段名称,也可以在整个扁平对象中搜索叶值。例如,以下请求搜索所有标记为 bug 的问题:

GET /test-index/_search
{
  "query": {
    "match": {"issue": "bug"}
  }
}

或者,如果您知道要搜索的子字段名称,请使用点表示法提供字段的路径:

GET /test-index/_search
{
  "query": {
    "match": {"issue.labels.category.level": "bug"}
  }
}

在这两种情况下,响应相同,都包含文档 2:

{
  "took": 1,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 1.0303539,
    "hits": [
      {
        "_index": "test-index",
        "_id": "2",
        "_score": 1.0303539,
        "_source": {
          "issue": {
            "number": "123457",
            "labels": {
              "version": "2.2",
              "category": {
                "type": "API",
                "level": "bug"
              }
            }
          }
        }
      }
    ]
  }
}

使用前缀查询,您可以搜索所有版本以 2. 开头的问题:

GET /test-index/_search
{
  "query": {
    "prefix": {"issue.labels.version": "2."}
  }
}

使用范围查询,您可以搜索所有版本在 2.0 到 2.1 之间的问题:

GET /test-index/_search
{
  "query": {
    "range": {
      "issue": {
        "gte": "2.0",
        "lte": "2.1"
      }
    }
  }
}

将子字段定义为扁平对象

您可以将 JSON 对象的子字段定义为扁平对象。例如,使用以下查询将 issue.labels 定义为 flat_object

PUT /test-index/
{
  "mappings": {
    "properties": {
      "issue": {
        "properties": {
          "number": {
            "type": "double"
          },
          "labels": {
            "type": "flat_object"
          }
        }
      }
    }
  }
}

由于 issue.number 不属于扁平对象,您可以使用它来聚合和排序文档。