subobjects

编辑

当索引文档或更新映射时,Elasticsearch 接受名称中包含点的字段,这些字段会扩展为其相应的对象结构。 例如,字段 metrics.time.max 被映射为一个 max 叶子字段,其父对象为 time,而 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" 字段。