2

1、概述

映射(Mapping)相当于数据表的表结构。
ElasticSearch中的映射(Mapping)用来定义一个文档,可以定义所包含的字段以及字段的类型、分词器及属性等等。

映射可以分为动态映射和静态映射。
(1)动态映射
我们知道,在关系数据库中,需要事先创建数据库,然后在该数据库实例下创建数据表,然后才能在该数据表中插入数据。
而ElasticSearch中不需要事先定义映射(Mapping),文档写入ElasticSearch时,会根据文档字段自动识别类型,这种机制称之为动态映射。

(2)静态映射
当然,在ElasticSearch中也可以事先定义好映射,包含文档的各个字段及其类型等,这种方式称之为静态映射。

2、动态映射实例

(1)新建索引

PUT /book

(2)查看空索引

GET /book/_mapping

{
  "book": {
    "mappings": {}
  }
}

(3)插入文档

PUT book/it/1
{
  "bookId":1,
  "bookName":"Java程序设计",
  "publishDate":"2018-01-12"
}

{
  "_index": "book",
  "_type": "it",
  "_id": "1",
  "_version": 1,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 0,
  "_primary_term": 1
}

(4)再次查看映射

GET /book/_mapping

{
  "book": {
    "mappings": {
      "it": {
        "properties": {
          "bookId": {
            "type": "long"
          },
          "bookName": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          },
          "publishDate": {
            "type": "date"
          }
        }
      }
    }
  }
}

bookId字段推测为long型,
bookName字段推测为text类型,
publishDate字段推测为date类型,
这些推测都是我们可以接受的。可见ElasticSearch的动态映射十分强大。

3、动态映射规则

JSON数据 自动推测的类型
null 没有字段被添加
true或false boolean型
小数 float型
数字 long型
日期 date或text
字符串 text
数组 由数组第一个非空值决定
JSON对象 object类型

4、静态映射

动态映射的自动类型推测功能并不是100%正确的,这就需要静态映射机制。
静态映射与关系数据库中创建表语句类型,需要事先指定字段类型。相对于动态映射,静态映射可以添加更加详细字段类型、更精准的配置信息等。

(1)新建映射

PUT books
{
  "mappings":{
    "it": {
       "properties": {
          "bookId": {"type": "long"},
          "bookName": {"type": "text"},
          "publishDate": {"type": "date"}
       }
    }
  }
}

(2)查看映射

GET /books/_mapping

{
  "books": {
    "mappings": {
      "it": {
        "properties": {
          "bookId": {
            "type": "long"
          },
          "bookName": {
            "type": "text"
          },
          "publishDate": {
            "type": "date"
          }
        }
      }
    }
  }
}

(3)插入数据

PUT books/it/1
{
  "bookId":"1",
  "bookName":"Java",
  "publishDate":"2018-01-12"

}

(4)查询

GET books/it/1

{
  "_index": "books",
  "_type": "it",
  "_id": "1",
  "_version": 1,
  "found": true,
  "_source": {
    "bookId": "1",
    "bookName": "Java",
    "publishDate": "2018-01-12"
  }
}

5、静态+动态

(1)加入不在静态映射的字段

PUT books/it/2
{
  "bookId":"2",
  "bookName":"Hadoop",
  "author":"chengyuqiang",
  "publishDate":"2018-01-13"

}

(2)查看索引

GET books/_mapping

{
  "books": {
    "mappings": {
      "it": {
        "properties": {
          "author": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          },
          "bookId": {
            "type": "long"
          },
          "bookName": {
            "type": "text"
          },
          "publishDate": {
            "type": "date"
          }
        }
      }
    }
  }
}

通过自动映射添加了新的不存在的字段 author

6、type设计失误

为什么映射类型被删除?

ES的索引类似于关系型数据库中的数据库,
一个映射类型则相当于关系型数据库中的一张表。

这是一个错误的类比,导致了错误的假设。
在一个关系型数据库中,表之间是相互独立的。
一个表中的列与另一个表中同名的列没有关系。然而在映射类型中却不是这样的。

在一个Elasticsearch的索引中,有相同名称字段的不同映射类型在Lucene内部是由同一个字段支持的。

换言之,看下面的这个例子,user 类型中的 user_name字段和tweet类型中的user_name字段实际上是被存储在同一个字段中,而且两个user_name字段在这两种映射类型中都有相同的定义(如类型都是 text或者都是date)。

这会导致一些问题,比如,当你希望在一个索引中的两个映射类型,一个映射类型中的 deleted 字段映射为一个日期数据类型的字段,而在另一个映射类型中的deleted字段映射为一个布尔数据类型的字段,这就会失败。

最重要的是,在一个索引中存储那些有很少或没有相同字段的实体会导致稀疏数据,并且干扰Lucene有效压缩文档的能力。


kyle
23 声望4 粉丝