「这是我参与2022首次更文挑战的第3天,活动详情查看:2022首次更文挑战」。
Elasticsearch---映射
1 概念:
ES中的mapping有点类似与RDB中“表结构”的概念,在MySQL中,表结构里包含了字段名称,字段的类型还有索引信息等。在Mapping里也包含了一些属性,比如字段名称、类型、字段使用的分词器、是否评分、是否创建索引等属性,并且在ES中一个字段可以有对个类型,字段的类型可以通过手动mapping创建,但是不能修改已经mapping过的字段,但可以新增字段数据类型的mapping。
Mapping是用来定义一个文档(document),以及它所包含的属性(field)是如何存储和索引的。比如,使用mapping来定义哪些字符串属性应该被看做全文本属性(full text fields)、哪些属性包含数字,日期或者地理位置、文档中的所有属性是否都能被索引(_all 配置)、日期的格式、自定义映射规则来执行动态添加属性。
2 查看mapping
GET /index/_mappings
3 字段的数据类型
不同的场景使用不通的类型.如: 如果是一个字符串类型的字段,可以使用 text类型,用于全文索引. 使用 keyword 类型用于排序(sort) 或者聚合(aggregations).另外,你可以通过(分词器)标准分词英文分词,法文分词以及来索引一个字符串。
3.1 核心数据类型
| 分类 | 字段的数据类型 |
| String 字符串型 | text和keyword |
| Numeric 数字型 | long, integer, short, byte, double, float, half_float, scaled_float |
| Date 日期型 | date |
| Boolean 布尔型 | boolean |
| Binary 二进制型 | binary |
| Range 范围型 | integer_range, float_range, long_range, double_range, date_range |
3.2 复合数据类型
| 分类 | 字段的数据类型 |
| Array 数组型 | 支持数组形式,不需要一个专有的字段数据类型 |
| Object 对象型 | object数据类型:表现形式其实就是单一的JSON对象 |
| Nested 嵌套型 | nested数据类型:表现形式是多个Object型组成的一个数组 |
3.3 Geo地理数据类型
| 分类 | 字段的数据类型 |
| Geo-point 地理坐标型 | geo_point数据类型:描述纬度/经度坐标 |
| Geo-Shape 地理图形型 | geo_shape数据类型:描述多边形等复杂形状 |
3.4 特定数据类型
| 分类 | 字段的数据类型 |
| IP型 | ip:描述IPv4 和 IPv6 地址 |
| Completion补全型 | completion:提供自动完成的提示 |
| Token count 令牌计数型 | token_count:用于统计字符串中的词条数量 |
| mapper-murmur3 型 | murmur3:计算哈希值在指数时间和并存储他们在索引中 |
| Attachment 附件型 | 查看mapper-attachments插件来支持索引附件,如微软Office格式,开放文档格式,EPUB,HTML等附件类型。 |
| Percolator 抽取型 | 接受特定领域查询语言(query-dsl)的查询 |
4 Mapping Types
每一个索引都有一个或多个映射类型,用于在一个索引中把文档划分为具有逻辑关系的分组。比如,用户文档应该存储为user 类型,博客应该放置于blogpost类型下。
每一个映射类型包含:
- Meta_fields(元数据) 元标签用于制定如何处理文档相关的元数据。例如元标签包含文档的 _index, _type,_id, 和_source 字段。
- Fields or properties(字段或属性) 每一个映射类型包含有一些与该类型相关的字段或者属性。比如一个user类型也许包含title,name,age属性,而blogpost类型也许包含title, body, user_id 和 created属性。在同一索引中,不同的映射类型下具有相同名称的属性具有相同的映射。
注意: 如果两个字段或者多个字段在不同type(表)的mapping中,但是这些type(表)都在相同的同一个index下,字段的映射的数据类型必须一致.
5 Meta-Fields
5.1 Identity meta-fields(文档标示元字段)
| 字段 | 描述 |
| _index | 文档所属的索引,多索引查询时,有时候只需要在特地索引名上进行查询,_index字段提供了便利,也就是说可以对索引名进行term查询、terms查询、聚合分析、使用脚本和排序。 |
| _uid | 复合字段包含了_type 和_id,elasticsearch6及之后弃用。现在,_type类型已被删除,文档由_id唯一标识,_uid字段仅作为查看_id字段以保持向后兼容。 |
| _type | 文档的mapping type(映射类型 ),在elasticsearch6及之后弃用。索引中的每一份文档都和一个 _type和_id唯一关联。 _type 字段本身的设计目标是为了索引更快查询。可被查询,聚合,排序使用,或者脚本里使用。 |
| _id | 文档 ID,在elasticsearch6之前因为支持多类型的存在,所以我们在一个索引中唯一标示文档需要同时用到 _type 和 _id,或者用_uid来作为唯一主键,elasticsearch6 及之后_id 就是索引的唯一主键。 |
5.2 Document source meta-fields(原文档元字段)
| 字段 | 描述 |
| _source | 文档的原生json字符串文档内容。,_source字段包含在索引时间传递的原始JSON文档正文。 _source字段本身没有编入索引(因此不可搜索),但它被存储,以便在执行获取请求(如get或search)时可以返回它。默认_source字段是开启的,也就是说,默认情况下存储文档的原始值。 |
| _size | 整个_source字段的大小 (以字节为单位),由 mapper-size 插件提供。 |
5.3 Indexing meta-fields(索引元字段)
| 字段 | 描述 |
| _all | 一个索引其他全部字段值的全能字段,_all字段是把其它字段拼接在一起的超级字段,所有的字段用空格分开,_all字段会被解析和索引,但是不存储。当你只想返回包含某个关键字的文档但是不明确地搜某个字段的时候就需要使用_all字段。默认是关闭的。在elasticsearch6及之后弃用。 |
| _field_names | 文档中包含非空值的所有字段,_field_names字段包含索引文档中字段的取值除null以外的任何值每个字段的名称。 一般使用此字段来查找对于特定字段具有或不具有任何非空值的文档。目前,一般来讲_field_names字段只包含具有doc_values并且默认关闭属性的字段名称。 |
| _ignored | elasticsearch 6.4之后添加元字段,_ignored 元字段索引和存储文档中由于ignore_malformed属性被ignored 的每个字段的名称。 |
5.4 Routing meta-field(路由元字段)
| 字段 | 描述 |
| _parent | 用于创建两个映射类型之间的父子关系。 |
| _routing | 默认是用的 文档_id元字段的值来路由,索引中的文档存储在特定的分片使用下面的公式决定:shard_num = hash(_routing) % num_primary_shards |
5.5 Other meta-field(其他元字段)
| 字段 | 描述 |
| _meta | 特定应用的元数据。 |
6 Mapping parameters(映射参数)
6.1 analyzer(分析器)
这个算是剩下的参数里面比较常见的了。 analyzer的使用流程一般是你可以先定义analyzer的分词方法,停用词等等--目的是决定text字段如何被转换成token。比如The quick Brown Foxes.这个text字段,可能会被分成quick, brown, fox(跟analyzer设置有关),这三个词会新成为一个字段被索引。这使得在很长的text用几个独立的token去查询变得效率很高。 另一方面在查询的时候也应该设置analyzer,保证查询的内容会用同样的analyzer分析去查询。
Elasticsearch 内置了许多 pre-defined analyzers(预定义的分析器),可以在不进一步配置的情况下使用。它还附带许多 character filters(字符过滤器),tokenizers(分词器)和Token Filters(标记过滤器)。可以用来组合配置每个索引的自定义analyzer(分析器)。
每一个查询,每一个字段或索引都可以指定分析器,在索引的时候,Elasticsearch 将按以下顺序查找 analyzer(分析器):
- 定义在字段映射中的 analyzer(分析器)。
- 索引设置中 default(默认)的 analyzer(分析器)。
- standard(标准的)analyzer(分析器)。
在查询时,还有几层 :
- 在 full-text query(全文查找)中定义的 analyzer(分析器)。
- 在字段映射中定义的 search_analyzer(搜索分析器)。
- 在字段映射中定义的 analyzer(分析器)。
- 在索引配置中 default_search(默认搜索的)analyzer(分析器)。
- 索引设置中 default(默认)的 analyzer(分析器)。
- standard(标准的)analyzer(分析器)。
6.2 normalizer(归一化)
normalizer(归一化)属性与 analyzer(分析器)类似,只不过它保证 analysis chain(分析链)生成单一的 token(词元),normalizer属性对于keyword类型来说的,其功能相当于text的analyzer属性。
normalizer(归一化)应用于索引 keyword(关键字)之前,以及诸如在 matchquery(匹配查询),查询解析器搜索 keyword fields(关键字字段)的时候.
6.3 boost(提升)
主要用来设置字段的权重,为了使查询的时候的相关性分数更高,个别字段可以自动 boost (提升)权重 – 通过相关性分数来进行计数 - 在查询的时候,boost(提升)参数。默认值是1.0。 通常被用来应用于词查询(前缀、范围、模糊查询都是不值得)。
6.4 Coerce(强制类型转换)
数据不总是干净的,比如你定义了一个字段是Integer,但是doc里是String的"5",此时可以自动。 coerce就是强制类型转换默认均为true,如果设置false,就不能把String的"5"放进Integer的字段。 可以通过这个 "index.mapping.coerce": false,将所有字段都定义成false,然后专门设置某个字段为true。
6.5 copy_to(合并参数)
copy_to参数允许你创建自定义的 _all 字段.换句换来说,可以将多个字段的值复制到group field(组字段),然后可以作为单个字段进行查询.例如, first_name和 last_name可以复制到 full_name字段中,是6.0以后_all字段的替换方案的使用。
6.6 doc_values(文档值)
首先数据结构和倒排索引正好相反,但是聚合操作、排序分析或者执行脚本他们不是用倒排索引那一套来解决的,我们不是通过单词找文档,而是通过文档找到某个字段的term情况。 doc_values是磁盘数据,在创建索引的时候建立,每一个doc存的跟_source数据一模一样,默认所有支持doc_values参数的字段都是开启的,如果没有聚合排序或者脚本访问的操作,可以关闭。
简单点理解就是可以字段值可以索引一个正排的索引,可以被排序和聚合操作。
6.7 dynamic(动态设置)
你可以不设置doc的mapping结构直接往一个索引里添加doc,这就是ES自带的动态添加实现的。如果你希望整体结构是固定的,某些字段或者其内部字段可以动态添加。
6.8 enabled(开启字段)
enabled设置只可以应用于映射类型和 object 字段,导致 Elasticsearch 完全跳过字段内容的解析.这个 JSON仍然可以从 _source 字段中检索,但是不能以任何其他方式搜索或存储。你想在_source看到它,但你又不想它被索引,比如session相关的数据这种。你可以将enabled设置为false。默认全部都是true。
6.9 fielddata(字段数据)
所有字段是默认被 indexed(被索引的),这使得它们是可搜索的.可以在脚本中排序,聚合和获取字段值,但是需要不同的搜索模式.
搜索需要回答一个问题 “哪个 document(文档)包含这个 term(词条)”,然而排序和聚合需要回答一个不同的问题 " 这个字段在这个 document(文档)中的值是多少?".
许多字段可以使用index-time,在磁盘上的doc_values支持这种数据访问模式, 但是text字段不支持doc_values。 相反,text 字段使用查询时存在于内存的数据结构 fielddata.这个数据结构是第一次将字段用于聚合,排序,或者脚本时基于需求构建的。它是通过读取磁盘上的每个 segment(片段)的整个反向索引来构建的,将 term(词条)和 document(文档)关系反转,并将结果存储在内存中,在JVM的堆中.
6.10 format (日期格式)
在JSON 文档中,日期表示为字符串.Elasticsearch 使用一组预先配置的格式来识别和解析这些字符串表示为 milliseconds-since-the-epoch in UTC.
除了内置格式,你可以使用熟悉的yyyy/MM/dd语法指定自己的自定义格式.
支持日期值的许多API还支持日期数学表达式,例如now-1m/d,即当前时间,减去一个月,向下舍入到最近的一天.
注: 格式设置在相同索引中相同名称的字段要有相同的设置.
6.11 ignore_above(忽略超越限制的字段)
字符串长度超过ignore_above设置的不会被索引和存储.选项对于防止Lucene term(词条)长度超过32766是有用的.ignore_above 的值是字符数,但 Lucene 计数的是字节。所以如果你使用具有许多非ASCII字符的UTF-8文本,则可能需要将限制设置为 32766/3 = 10922,因为UTF-8字符可能占用至多3个字节。
6.12 ignore_malformed(忽略格式不对的数据)
有时候你对接受到的数据不会有太多的控制.一个用户可能发送一个日期类型的登录字段,另一个用户发送一个邮箱地址的登录字段.
尝试将错误的数据类型索引到字段中,默认情况会抛出异常,并拒绝整个document(文档).ignore_malformed 参数(如果设置为true)允许忽略该异常。格式不正确的字段不会被索引,但文档中的其他字段正常处理。
6.13 include_in_all(_all 查询包含字段)
include_in_all参数用于控制_all查询时需要包含的字段.默认为true,除非在index设置成no,include_in_all 参数也可作用于type(类型)、文档或者嵌套字段,这样该作用域下的所有字段将继承该属性。
6.14 index_options(索引设置)
index_options参数用于控制添加到倒排索引中的信息,服务于搜索和高亮等目的。他可以包括以下参数:
docs: 只有文档编号被索引。能够回答的问题只有此 term(词条)是否存在于此字段。
freqs:文档编号和term(词条)的频率会被索引。term(词条)频率用于给搜索评分,重复出现的term(词条)评分将高于单个出现的term(词条)。
positions:文档编号、term frequencies(词条频率)和term(词条)位置(或顺序)将被索引。Position被用于
proximity queries (邻近查询)和phrase queries(短语查询)。
offsets: 文档编号、term(词条)频率,位置,起始和结尾字符偏移量(用于映射该 term (词条)到原始字符串)将被索引。Offset用于postings highlighter。
被分析器分析的字符串字段使用 position 作为默认值,其他的字段使用 docs 作为默认值。
6.15 index (索引)
index 可以设置的值为analyzed(默认值),not_analyzed,和 no.
如果设置为analyzed,该字段将被编入索引以供搜索.
如果设置为no,将无法搜索该字段.
在基于字符串的字段中,还有一个额外的选项not_analyzed.此设置意味着字段将不经分析而编入索引(使用原始值编入索引),在搜索过程中必须精确全部匹配. 索引属性设置为no,将使inlude_in_all属性失效,也就是会加入到+all字段中,此字段值也就无法参与全文索引.
6.16 fields(字段)
我们经常会因为不同的目的将同一个字段用不同的方式索引。这就相当于实现了multi-fields。例如,一个string类型字段可以被映射成text字段作为full-text进行搜索,同时也可以作为keyword字段用于排序和聚合
备注: Multi_fields不会改变原始的_source字段。
注意: 同一索引相同字段名可以设置不同的fields。可以通过PUT mapping API 在已经存在的字段加入新的multi-fields。
6.17 Norms (标准信息)
norms 存储各种标准化因子,为后续查询计算文档对该查询的匹配分数提供依据。
虽然 norms 参数对评分很有用,但他需要占用大量的磁盘空间(通常是为了索引每个文档中每个字段每个字节的顺序,甚至不包含此字段的文档也是如此)。因此,如果你不需要计算此字段的评分,应该在改字段取消 norms 的功能.特别是那些仅仅只是用做过滤条件或者聚合条件的字段。
注意:
同一索引具有相同名字的字段必须设置相同的 norms 值。norms 将会因为已存在的字段使用 PUT mapping API而失效。
norms 可以在之后被取消(但不能再次启用)
备注:
norms 不会被立刻删除,但是当继续索引新文档时,旧 segments(段)将合并到新的 segments(段)后,norms 将被删除.当分数计算作用在这种删除 norms 的字段上时,可能会出现不一致的结果,因为其中有些文档含有 norms,另外一些文档不含有 norms.
6.18 null_value(空值)
null 值不能被索引或者搜索.当一个字段被设置成 null(或者一个空数组,或者值全为 null 的数组)时, 该字段将被视为没有值。
null_value 参数允许你用一个特殊的值替换一个显示的 null 值, 以确保这个字段能被索引和搜索。 重点 null_value必须设置成相同类型的参数。例如,一个long型的字段不能被设置成string类型的null_value。
6.19 position_increment_gap(短语位置间隙)
解析的 text fields(文本字段)会将 term(词根)的位置考虑进去,目的是为了能支持 proximity queries(近似查询)和 phrase queries(短语查询)。当我们索引一个含有多个值的 text fields(文本字段)时,会在各个值之间加入一个"假想"的间隙,这样就可以阻止大多数跨值匹配的短语查询。这个间隙的大小使用 position_increment_gap 参数来设定,默认值是100。
注意:
同一索引中相同名字的字段可以设定不同的position_increment_gap值。他的值可以通过PUT mapping API使用同名字段来进行更新。
6.20 properties (属性)
type(类型)映射、object fields(对象字段)和nested fields(嵌入字段)包含的 sub-fields(子字段),称之为 properties(属性)。这些 properties(属性)可以为任意 datatype(数据类型),包括 object(对象)和 nested(嵌入数据)。properties(属性)可以通过以下方式加入:
- 通过创建索引是明确地定义他们。
- 通过使用PUT mapping API添加或更新映射类型时明确地定义他们。
- 索引包含新字段的文档时动态的加入。
注意
同一索引下的相同名字的字段可以设置不同的properties(属性)。新的properties(属性)可以通过PUT mapping API加入已经存在的字段。
6.21 search_analyzer (搜索分析器)
通常情况下,我们在搜索和创建索引时使用的是同一分析器,以确保我们搜索是的词根与倒排索引中的词根拥有相同的格式。
但是有时我们又会有意识的在搜索时使用不同的分析器,例如使用edge_ngram解析器自动解析。
默认情况下,查询将会使用字段映射时定义的分析器,但也能通过search_analyzer设置来进行修改
注意
同一索引相同名字的字段search_analyzer 设置必须相同。他的值可以通过PUT mapping API进行覆盖修改。
6.22 similarity (匹配方法)
lasticsearch 允许你为每一个字段配置一个得分算法或similarity(匹配算法)。similarity设置提供了一个简单的方式让你选择匹配算法,而不仅仅是默认的TF/IDF算法,比如可以选择BM25。
similarity主要用于text字段,但也可用于其他类型的字段。
自定义匹配算法可以通过修改内置匹配方法的参数来达到目的。要获取此专业选项更详细的解释,可以参考similarity module。
对于能跳出以上限制,而不用任何其他配置的匹配算法只有一下两种:
BM25:Okapi BM25算法。这个算法是Elasticsearch和Lucene的默认算法。可以参考Pluggable Similarity Algorithms获取更详细的资料。
classic:TF/IDF 算法,也是Elasticsearch和Lucene的默认算法之一。可以参考 Lucene’s Practical Scoring Function 获取更详细的资料。
similarity可以在字段第一次创建时在字段级别进行设置
6.23 store(存储)
store 的意思是,是否在 _source 之外在独立存储一份,这里要说一下 _source 这是源文档,当你索引数据的时候, elasticsearch 会保存一份源文档到 _source ,如果文档的某一字段设置了 store 为 yes (默认为 no),这时候会在 _source 存储之外再为这个字段独立进行存储,这么做的目的主要是针对内容比较多的字段,放到 _source 返回的话,因为_source 是把所有字段保存为一份文档,命中后读取只需要一次 IO,包含内容特别多的字段会很占带宽影响性能,通常我们也不需要完整的内容返回(可能只关心摘要),这时候就没必要放到 _source 里一起返回了(当然也可以在查询时指定返回字段)。
备注 存储的字段将作为数组返回
为了保持一致性,存储的字段将总是作为数据返回,因为没有办法知道原始字段是单个值、多值还是空数组。
如果你需要原始值,你应该从 _source字段返回。
6.24 Term_vectors(词根信息)
词属性可以取6值,它定义是否要计算该字段的Lucene词向量(term vector).如果使用高亮,那就需要计算这个词向量 Term vectors是通过分析器解析产生的信息,包括:
- 一组terms(词根)
- 每个词根的位置(顺序)
- 映射词根的首字符和尾字符与原始字符串原点的偏移量
7 Dynamic Mapping(动态映射)
自动的检测和添加新的类型以及字段的过程,称之为动态映射。
PUT data/_doc/1
{ "count": 5 }
上面这个例子会自动创建名为 data 的索引,其中包含名为 _doc 的 mapping type(映射类型),以及名为 count 的 long 数据类型。 自动的检测和添加新的类型以及字段的过程,称之为动态映射。你可以根据需要定制动态映射的规则: Dynamic field mappings(动态字段映射):控制动态字段发现的规则。 Dynamic templates(动态模板):利用自定义规则来配置动态添加的字段的映射。
无论是自动还是显式的创建索引,Index templates(索引模板)都允许你为一个新的索引配置 mappings,settings 和 aliases(别名)。
总结
本篇文章就到这里就结束了,后续会再补充,还有很多不完善之处。
本文参考资料:Elasticsearch官方文档地址
著作权归NoLongerConfused所有。商业转载请联系NoLongerConfused获得授权,非商业转载请注明出处。