subobjects

编辑

在索引文档或更新映射时,Elasticsearch 接受名称中包含点的字段,这些字段会被扩展到其对应的对象结构。例如,字段 metrics.time.max 被映射为一个 max 叶子字段,它有一个父 time 对象,属于其父 metrics 对象。

这种默认行为在大多数情况下是合理的,但在某些情况下会造成问题,例如字段 metrics.time 也保存了一个值,这在索引指标数据时很常见。如果一个文档同时为 metrics.time.maxmetrics.time 保存了值,则会被拒绝,因为 time 需要同时作为叶子字段保存值,也需要作为对象保存 max 子字段。

subobjects 设置只能应用于顶级映射定义和 object 字段,它禁用对象保存更多子对象的能力,并使存储字段名称包含点并共享公共前缀的文档成为可能。从上面的例子来看,如果对象容器 metricssubobjects 设置为 false,它可以直接保存 timetime.max 的值,而无需任何中间对象,因为字段名称中的点将被保留。

resp = client.indices.create(
    index="my-index-000001",
    mappings={
        "properties": {
            "metrics": {
                "type": "object",
                "subobjects": False,
                "properties": {
                    "time": {
                        "type": "long"
                    },
                    "time.min": {
                        "type": "long"
                    },
                    "time.max": {
                        "type": "long"
                    }
                }
            }
        }
    },
)
print(resp)

resp1 = client.index(
    index="my-index-000001",
    id="metric_1",
    document={
        "metrics.time": 100,
        "metrics.time.min": 10,
        "metrics.time.max": 900
    },
)
print(resp1)

resp2 = client.index(
    index="my-index-000001",
    id="metric_2",
    document={
        "metrics": {
            "time": 100,
            "time.min": 10,
            "time.max": 900
        }
    },
)
print(resp2)

resp3 = client.indices.get_mapping(
    index="my-index-000001",
)
print(resp3)
response = client.indices.create(
  index: 'my-index-000001',
  body: {
    mappings: {
      properties: {
        metrics: {
          type: 'object',
          subobjects: false,
          properties: {
            time: {
              type: 'long'
            },
            'time.min' => {
              type: 'long'
            },
            'time.max' => {
              type: 'long'
            }
          }
        }
      }
    }
  }
)
puts response

response = client.index(
  index: 'my-index-000001',
  id: 'metric_1',
  body: {
    'metrics.time' => 100,
    'metrics.time.min' => 10,
    'metrics.time.max' => 900
  }
)
puts response

response = client.index(
  index: 'my-index-000001',
  id: 'metric_2',
  body: {
    metrics: {
      time: 100,
      'time.min' => 10,
      'time.max' => 900
    }
  }
)
puts response

response = client.indices.get_mapping(
  index: 'my-index-000001'
)
puts response
const response = await client.indices.create({
  index: "my-index-000001",
  mappings: {
    properties: {
      metrics: {
        type: "object",
        subobjects: false,
        properties: {
          time: {
            type: "long",
          },
          "time.min": {
            type: "long",
          },
          "time.max": {
            type: "long",
          },
        },
      },
    },
  },
});
console.log(response);

const response1 = await client.index({
  index: "my-index-000001",
  id: "metric_1",
  document: {
    "metrics.time": 100,
    "metrics.time.min": 10,
    "metrics.time.max": 900,
  },
});
console.log(response1);

const response2 = await client.index({
  index: "my-index-000001",
  id: "metric_2",
  document: {
    metrics: {
      time: 100,
      "time.min": 10,
      "time.max": 900,
    },
  },
});
console.log(response2);

const response3 = await client.indices.getMapping({
  index: "my-index-000001",
});
console.log(response3);
PUT my-index-000001
{
  "mappings": {
    "properties": {
      "metrics": {
        "type":  "object",
        "subobjects": false, 
        "properties": {
          "time": { "type": "long" },
          "time.min": { "type": "long" },
          "time.max": { "type": "long" }
        }
      }
    }
  }
}

PUT my-index-000001/_doc/metric_1
{
  "metrics.time" : 100, 
  "metrics.time.min" : 10,
  "metrics.time.max" : 900
}

PUT my-index-000001/_doc/metric_2
{
  "metrics" : {
    "time" : 100, 
    "time.min" : 10,
    "time.max" : 900
  }
}

GET my-index-000001/_mapping
{
  "my-index-000001" : {
    "mappings" : {
      "properties" : {
        "metrics" : {
          "subobjects" : false,
          "properties" : {
            "time" : {
              "type" : "long"
            },
            "time.min" : { 
              "type" : "long"
            },
            "time.max" : {
              "type" : "long"
            }
          }
        }
      }
    }
  }
}

metrics 字段不能包含其他对象。

包含扁平路径的示例文档

包含对象(配置为不包含子对象)及其叶子子字段的示例文档

保留字段名中点的结果映射

也可以将整个映射配置为不支持子对象,在这种情况下,文档只能包含叶子子字段。

resp = client.indices.create(
    index="my-index-000001",
    mappings={
        "subobjects": False
    },
)
print(resp)

resp1 = client.index(
    index="my-index-000001",
    id="metric_1",
    document={
        "time": "100ms",
        "time.min": "10ms",
        "time.max": "900ms"
    },
)
print(resp1)
response = client.indices.create(
  index: 'my-index-000001',
  body: {
    mappings: {
      subobjects: false
    }
  }
)
puts response

response = client.index(
  index: 'my-index-000001',
  id: 'metric_1',
  body: {
    time: '100ms',
    'time.min' => '10ms',
    'time.max' => '900ms'
  }
)
puts response
const response = await client.indices.create({
  index: "my-index-000001",
  mappings: {
    subobjects: false,
  },
});
console.log(response);

const response1 = await client.index({
  index: "my-index-000001",
  id: "metric_1",
  document: {
    time: "100ms",
    "time.min": "10ms",
    "time.max": "900ms",
  },
});
console.log(response1);
PUT my-index-000001
{
  "mappings": {
    "subobjects": false 
  }
}

PUT my-index-000001/_doc/metric_1
{
  "time" : "100ms", 
  "time.min" : "10ms",
  "time.max" : "900ms"
}

整个映射被配置为不支持对象。

文档不支持对象。

现有字段和顶级映射定义的 subobjects 设置不能更新。

自动扁平化对象映射

编辑

通常建议使用带点的字段名来定义配置了 subobjects: false 的对象的属性(如第一个示例所示)。但是,也可以在映射中将这些属性定义为子对象。在这种情况下,映射将在存储之前自动扁平化。这使得更容易重用现有映射,而无需重写它们。

请注意,当在配置为 subobjects: false 的对象下定义的对象映射上设置某些 映射参数 时,自动扁平化将不起作用。

  • enabled 映射参数不能为 false
  • dynamic 映射参数不能与父级的隐式或显式值相矛盾。例如,当在映射的根目录中将 dynamic 设置为 false 时,将 dynamic 设置为 true 的对象映射器无法自动扁平化。
  • subobjects 映射参数不能显式设置为 true
resp = client.indices.create(
    index="my-index-000002",
    mappings={
        "properties": {
            "metrics": {
                "subobjects": False,
                "properties": {
                    "time": {
                        "type": "object",
                        "properties": {
                            "min": {
                                "type": "long"
                            },
                            "max": {
                                "type": "long"
                            }
                        }
                    }
                }
            }
        }
    },
)
print(resp)

resp1 = client.indices.get_mapping(
    index="my-index-000002",
)
print(resp1)
response = client.indices.create(
  index: 'my-index-000002',
  body: {
    mappings: {
      properties: {
        metrics: {
          subobjects: false,
          properties: {
            time: {
              type: 'object',
              properties: {
                min: {
                  type: 'long'
                },
                max: {
                  type: 'long'
                }
              }
            }
          }
        }
      }
    }
  }
)
puts response

response = client.indices.get_mapping(
  index: 'my-index-000002'
)
puts response
const response = await client.indices.create({
  index: "my-index-000002",
  mappings: {
    properties: {
      metrics: {
        subobjects: false,
        properties: {
          time: {
            type: "object",
            properties: {
              min: {
                type: "long",
              },
              max: {
                type: "long",
              },
            },
          },
        },
      },
    },
  },
});
console.log(response);

const response1 = await client.indices.getMapping({
  index: "my-index-000002",
});
console.log(response1);
PUT my-index-000002
{
  "mappings": {
    "properties": {
      "metrics": {
        "subobjects": false,
        "properties": {
          "time": {
            "type": "object", 
            "properties": {
              "min": { "type": "long" }, 
              "max": { "type": "long" }
            }
          }
        }
      }
    }
  }
}
GET my-index-000002/_mapping
{
  "my-index-000002" : {
    "mappings" : {
      "properties" : {
        "metrics" : {
          "subobjects" : false,
          "properties" : {
            "time.min" : { 
              "type" : "long"
            },
            "time.max" : {
              "type" : "long"
            }
          }
        }
      }
    }
  }
}

metrics 对象可以包含将被自动扁平化的其他对象映射。此级别的对象映射不能设置如上所述的某些映射参数。

此字段将在映射存储之前自动扁平化为 "time.min"

可以通过查看索引映射来检查自动扁平化的 "time.min" 字段。