Mapping

予早 2025-10-05 22:41:35
Categories: Tags:

Mapping

Document 元数据字段

Field 数据类型

https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html

通用类型

对象和关系类型

结构化数据类型

Multi Field 多重字段 当我们需要对一个字段进行多种不同方式的索引时,可以使用fields多重字段定义。如一个字符串字段即需要进行text分词索引,也需要进行keyword 关键字索引来支持排序、聚合;或需要用不同的分词器进行分词索引。

nested

array 扁平化与 nested 独立子文档

Lucene 中会将文档进行扁平化处理,需要手动指定nested构建层次关系

PUT /array2nested
{
  "mappings": {
    "properties": {
      "array_field": {
        "type": "object",
        "properties": {
          "field1": {"type": "keyword"},
          "field2": {"type": "long"},
          "field3": {"type": "date"}
        }
      },
      "nested_field": {
        "type": "nested",
        "properties": {
          "field1": {"type": "keyword"},
          "field2": {"type": "long"},
          "field3": {"type": "date"}
        }
      }
    }
  }
}

创建三个示例文档,其中每个文档的 array_field 和 nested_field 数据完全一样

POST /array2nested/_doc/1
{
  "array_field": [
    {"field1": "A", "field2": 10, "field3": "2025-09-20"},
    {"field1": "B", "field2": 20, "field3": "2025-09-21"}
  ],
  "nested_field": [
    {"field1": "A", "field2": 10, "field3": "2025-09-20"},
    {"field1": "B", "field2": 20, "field3": "2025-09-21"}
  ]
}


POST /array2nested/_doc/2
{
  "array_field": [
    {"field1": "A", "field2": 20, "field3": "2025-09-20"},
    {"field1": "C", "field2": 30, "field3": "2025-09-22"}
  ],
  "nested_field": [
    {"field1": "A", "field2": 20, "field3": "2025-09-20"},
    {"field1": "C", "field2": 30, "field3": "2025-09-22"}
  ]
}


POST /array2nested/_doc/3
{
  "array_field": [
    {"field1": "B", "field2": 20, "field3": "2025-09-21"},
    {"field1": "C", "field2": 40, "field3": "2025-09-23"}
  ],
  "nested_field": [
    {"field1": "B", "field2": 20, "field3": "2025-09-21"},
    {"field1": "C", "field2": 40, "field3": "2025-09-23"}
  ]
}


// Lucene 对数组扁平化处理:
// array_field.field1: ["B", "C"]
// array_field.field2: [20, 40]
// array_field.field3: ["2025-09-21", "2025-09-23"]

查询 field1 = A 且 field2 = 20,预期为查询结果为id=2的文档

// 查 object 数组
// _id=1、2 都命中
// 1 号文档里 A 和 20 并不在同一个对象,但被扁平化后混在一起了
GET array2nested/_search
{
  "query": {
    "bool": {
      "must": [
        { "term": { "array_field.field1": "A" }},
        { "term": { "array_field.field2": 20 }}
      ]
    }
  }
}


// 查 nested 数组
// 只有 `_id=2` 命中 因为 nested 把每个对象当独立子文档,字段必须**同时出现在同一子文档**才算匹配。
GET array2nested/_search
{
  "query": {
    "nested": {
      "path": "nested_field",
      "query": {
        "bool": {
          "must": [
            { "term": { "nested_field.field1": "A" }},
            { "term": { "nested_field.field2": 20 }}
          ]
        }
      }
    }
  }
}

Mapping 参数

dynamic

https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/dynamic

dynamic 用于控制包含非 mapping 定义字段的一个文档插入该索引时的行为。包含四种取值:

coerce

https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/coerce

用于控制是否允许对文档中的字段值进行强制类型转换。**默认值为 true**,即默认允许强制类型转换。当文档中的字段值类型与映射中定义的类型不匹配时,如果启用了 coerce,Elasticsearch 会尝试自动将该值转换为映射中定义的类型。如果禁用 coerce,则必须确保文档中的字段值类型与映射中定义的类型完全一致,否则会导致文档索引失败。

如果映射中定义字段类型为 integer,但文档中传入的是字符串 "123",启用 coerce 后,Elasticsearch 会自动将其转换为整数 123。如果传入的是 "abc",则转换失败,仍然会抛出异常。

[!IMPORTANT]

coerce 为 true 时启用强制类型转换,会以数据转换后的值建立索引,而 _source 中依然原样存储,有可能会造成定义类型与实际类型的不一致。例如,索引中 age 被定义为 long 类型,但创建文档时 age 值为"18",则底层会以18建立索引,但查询文档时返回的 _source 中依然会是"18",且有可能文档创建时 age 值为18,这样会造成该索引中不同文档 _source 中返回类型不一样,以及 索引中字段类型与 _source 中类型不一样,为客户端处理数据造成问题。