1.映射(Mapping)
映射是定义文档及其包含的字段的存储和索引方式的过程。例如,使用映射来定义:
- 应将哪些字符串字段视为全文字段。
- 哪些字段包含数字,日期或地理位置。
- 是否应将文档中所有字段的值索引到catch-all
_all
字段中。 - 日期值 的格式。
- 用于控制动态添加字段的映射的自定义规则 。
1.1 映射类型(对比于数据库中的一个表)
每个索引都有一种映射类型,用于确定文档的索引方式。 在6.0.0中已弃用映射类型(即只有一个固定的类型名,不能自定义)。
映射类型具有(这个属于内容,还是可以自定义的):
- 元数据字段
- 元字段用于自定义文档的元数据关联的处理方式。元数据字段包括
-
_index 表示属于哪个索引
_type 类型名
_id 文档的id,唯一标识
_source 文档的原始数据(对比于数据库表中的一条记录)
- _routing 文档对应的路由信息(控制文档写到哪一个分片上,默认是使用id进行hash)
- 字段或属性
- 映射类型包含字段列表或
properties
与文档相关的列表。
废弃原因
传统数据库中同一个数据库下的多个表之间是互相独立的
es中同一个索引下的不同映射类型底层由ucene实例支持,不同类型下的相同名称的字段需要是相同的类型,因为lucene无法区分来自哪个type。
7.x之后每个索引只有一个type,名字为_doc
1.2 字段数据类型(对比于数据库的列的定义,只是es没有固定的列)
每个字段都有一个数据type
,可以是:
- 常见简单类型
- text 用于全文搜索,一般用于存储要搜索的字符串,如微博正文
- keyword 用于精确搜索,过滤结果。值可以是字符串或单个单词
- date 日期类型
- long、integer、shot、byte... 数字类型
- 一种支持JSON的分层特性的类型,如
object
或nested
。 - 或一种特殊类型如:
geo_point
,geo_shape
或completion
。
为不同目的以不同方式索引相同字段通常很有用。例如,string字段
可以索引为text
用于全文搜索,或者keyword
字段用于排序或聚合。
1.2.1 设置参数防止映射爆炸(映射字段过多导致问题,对比于数据库的列过多)
在索引中定义太多字段是一种可能导致映射爆炸的情况,这可能导致内存不足错误和难以恢复的情况。
这个问题可能比预期更常见。例如,考虑插入的每个新文档引入新字段的情况。这在动态映射中非常常见。每次文档包含新字段时,这些字段最终都会出现在索引的映射中。
随着映射的增加,可能会成为一个问题。以下设置允许您限制可手动或动态创建的字段映射的数量,以防止错误的文档导致映射爆炸:
index.mapping.total_fields.limit
- 索引中的最大字段数。字段和对象映射以及字段别名都计入此限制。默认值为
1000
。 index.mapping.depth.limit
- 字段的最大深度,以内部对象的数量来衡量。例如,如果所有字段都是在根对象级别定义的,则深度为
1
。如果有一个对象映射,则深度为2
,等等。默认值为20
。 index.mapping.nested_fields.limit
nested
索引中 的最大字段数,默认为50
。使用100个嵌套字段索引1个文档实际上索引101个文档,因为每个嵌套文档都被索引为单独的隐藏文档。
1.3 动态映射(根据字段的值自动推断字段的类型)
在使用之前不需要定义字段和映射类型。
由于动态映射,只需索引文档即可自动添加新的字段名称。同一个字段第一次出现的时候就确定了字段类型,后续此字段必须符合这个字段类型。
1.4 显式映射(对比与数据库中的定义表结构)
您对数据的了解比Elasticsearch可以猜到的更多,因此虽然动态映射对于入门很有用,但在某些时候您需要指定自己的显式映射。
您可以在创建索引时创建字段映射 ,也可以使用PUT映射API将字段添加到现有索引。
1.5 映射参数
1.5.1 analyzer
作用:
指定分词器,将对应的text类型数据分割成独立的单词(token或者terms)。
作用时间:
索引(分词并存储 ,建立倒排索引)和查询(将查询字段分词)
作用范围:
单词查询,单个字段,单次索引都可以指定分词器。如果没有指定则使用默认的standard分词器。
curl -X PUT "localhost:9200/my_index" -H 'Content-Type: application/json' -d' { "mappings": { "_doc": { "properties": { "text": { "type": "text", //这里没有指定analyzer,所以使用默认的standard分析器 "fields": { //这个字段的作用是,使用同一份数据,进行不同的处理 "english": { //定义字段名为english "type": "text", //字段类型为text "analyzer": "english" //英文分词器,es内置的 } } } } } } } ' curl -X GET "localhost:9200/my_index/_analyze" -H 'Content-Type: application/json' -d' { "field": "text", "text": "The quick Brown Foxes." } ' curl -X GET "localhost:9200/my_index/_analyze" -H 'Content-Type: application/json' -d' { "field": "text.english", //指定这个字段,则会使用其上定义的英文分词器 "text": "The quick Brown Foxes." } '
1.6 更新现有字段映射
已经存在的字段映射无法更新。更改映射意味着使已索引的文档无效。
相反,你应该创建正确映射一个新的索引,并调用reindex将数据进行转换到新的索引中。如果您只想重命名字段而不更改其映射,则引入alias
字段可能是有意义的。
1.7 映射示例
创建索引时可以指定映射,如下所示:
curl -X PUT "localhost:9200/my_index" -H 'Content-Type: application/json' -d' { "mappings": { "_doc": { //映射类型为 _doc "properties": { //定义字段或者properties "title": { "type": "text" }, //定义字段title的字段类型为text "name": { "type": "text" }, "age": { "type": "integer" }, "created": { "type": "date", "format": "strict_date_optional_time||epoch_millis" } } } } } '