扁平对象字段类型
2.7 版引入
在 OpenSearch 中,您无需在索引文档之前指定映射。如果您未指定映射,OpenSearch 会使用动态映射自动映射文档中的每个字段及其子字段。当您摄入日志等文档时,您可能无法提前知道每个字段的子字段名称和类型。在这种情况下,动态映射所有新子字段可能会迅速导致“映射爆炸”,即字段数量的不断增长可能会降低您的集群性能。
扁平对象字段类型通过将整个 JSON 对象视为字符串来解决此问题。JSON 对象中的子字段可以使用标准点路径表示法访问,但它们未被索引以进行快速查找。
点表示法中字段值的最大长度为 224 − 1。
扁平对象字段类型提供以下优势:
- 高效读取:获取性能与关键字字段类似。
- 内存效率:将整个复杂的 JSON 对象存储在一个字段中,而无需索引其所有子字段,从而减少了索引中的字段数量。
- 空间效率:OpenSearch 不会为扁平对象中的子字段创建倒排索引,从而节省了空间。
- 迁移兼容性:您可以将数据从支持类似扁平类型的系统迁移到 OpenSearch。
将字段映射为扁平对象适用于字段及其子字段主要用于读取而非用作搜索条件的情况,因为子字段未被索引。扁平对象对于具有大量字段或您不提前知道键的对象非常有用。
扁平对象支持带有点路径表示法和不带点路径表示法的精确匹配查询。有关支持的查询类型的完整列表,请参阅支持的查询。
在文档中搜索嵌套字段的特定值可能效率低下,因为它可能需要对索引进行完整扫描,这可能是一个昂贵的操作。
扁平对象不支持:
- 类型特定解析。
- 数值操作,例如数值比较或数值排序。
- 文本分析。
- 高亮显示。
- 使用点表示法对子字段进行聚合。
- 按子字段过滤。
支持的查询
扁平对象字段类型支持以下查询:
限制
OpenSearch 2.7 中扁平对象存在以下限制:
- 扁平对象不支持开放参数。
- 不支持使用 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
不是扁平对象的一部分,所以您可以使用它来聚合和排序文档。