参考:https://www.phpmianshi.com/?id=168
Mapping简介#
mapping 是用来定义文档及其字段的存储方式、索引方式的手段,例如利用mapping
来定义以下内容:
-
哪些字段需要被定义为全文检索类型
-
哪些字段包含
number
、date、布尔、浮点
类型等 -
格式化时间格式
-
自定义规则,用于控制动态添加字段的映射
自定义mapping
mapping中的字段类型一旦设置,禁止直接修改,因为 lucene实现的倒排索引生成后不允许修改,应该重新建立新的索引,然后做reindex操作。
但是可以新增字段,通过 dynamic 参数来控制字段的新增,这个参数的值如下:
-
true:默认值,表示允许选自动新增字段
-
false:不允许自动新增字段,但是文档可以正常写入,但无法对字段进行查询等操作
-
strict:严格模式,文档不能写入,报错
自定义mapping 的步骤:
-
写一条文档到es的临时索引中,获取es自动生成的mapping
-
修改第一步得到的mapping,自定义相关配置
-
使用第2步的mapping创建实际的索引
Mapping Type#
每个索引都拥有唯一的 mapping type
,用来决定文档将如何被索引。mapping type
由下面两部分组成
-
Meta-fields
元字段用于自定义如何处理文档的相关元数据。 元字段的示例包括文档的_index,_type,_id和_source字段。 -
Fields or properties
映射类型包含与文档相关的字段或属性的列表。
示例
创建index并设置mapping
PUT my_index { "mappings": { "dynamic": false, "properties": { "title": { "type": "text" }, "name": { "type": "keyword" }, "age": { "type": "integer" } } } }
查看mapping
{ "my_index" : { "mappings" : { "dynamic" : "false", "properties" : { "age" : { "type" : "integer" }, "name" : { "type" : "keyword" }, "title" : { "type" : "text" } } } } }
写入数据
POST my_index/_doc/1 { "title":"hello world", "desc":"this is a desc" }
注意,这里在mapping设置中,”dynamic”: false,表示在写入文档时,如果写入字段不存在也不会报错。这里的desc字段就是不存在的字段
查看,可以通过 title字段查询到文档的内容,但是通过 desc 查询是搜不到的。
get my_index/_search { "query":{ "match":{ "title":"hello" } } }
大家可以试着把 dynamic设置成 strict模式试试,在strict 模式下插入不存在的字段将会出现报错
copy_to参数
作用是将该字段的值复制到目标字段,实现类似_all的作用。不会出现在_source中,只能用来搜索。
PUT my_index { "mappings": { "properties": { "first_name": { "type": "text", "copy_to": "full_name" }, "last_name": { "type": "text", "copy_to": "full_name" }, "full_name": { "type": "text" } } } }
full_name的内容就是从 first_name 和 last_name 中复制过来的
创建一个新的文档,文档只需要写first_name 和 last_name
PUT my_index/_doc/1 { "first_name": "john", "last_name": "smith" }
查询一下,查询包含关键字john smith的文档,必须同时包含两个关键字才返回
GET my_index/_search { "query": { "match": { "full_name": { "query": "john smith", "operator": "and" } } } }
index参数
index参数作用是控制当前字段是否被索引,默认为true,false表示不记录,即不可被搜索。当在es中存储了一些不想要被检索的字段如身份证、手机等,这是对于这些字段就可以使用index设置为false,这样有一定的安全性还可以节省空间
index_options参数
index_options的作用是用于控制倒排索引记录的内容,有如下四种配置:
-
docs:只记录doc id
-
freqs:记录doc id 和term frequencies
-
positions:记录doc id、 term frequencies和term position
-
offsets:记录doc id、 term frequencies、term position、character offsets
text类型的默认配置为positions,其他默认为docs。记录的内容越多,占据的空间越大。
null_value参数
这个参数的作用是当字段遇到null值的时候的处理策略,默认为null,即空值,此时es会忽略该值。可以通过这个参数设置某个字段的默认值。
字段类型
-
字符串类型:text、keyword(不会分词)
-
数值类型:long、integer、short、byte、double、float、half_float
-
日期类型:date
-
布尔类型:boolean
-
二进制类型:binary
-
范围类型:integer_range、float_range、long_range、double_range、date_range
-
数组类型:array
-
对象类型:object
-
嵌套类型:nested object
-
地理位置数据类型:geo_point、geo_shape
-
专用类型:ip(记录ip地址)、completion(实现自动补全)、token_count(记录分词数)、murmur3(记录字符串hash值)
针对同一字段支持多种字段类型可以更好地满足我们的搜索需求,例如一个string
类型的字段可以设置为text
来支持全文检索,与此同时也可以让这个字段拥有keyword
类型来做排序和聚合,另外我们也可以为字段单独配置分词方式,例如"analyzer": "ik_max_word"
text 类型#
text
类型的字段用来做全文检索,例如邮件的主题、淘宝京东中商品的描述等。这种字段在被索引存储前先进行分词,存储的是分词后的结果,而不是完整的字段。text
字段不适合做排序和聚合。如果是一些结构化字段,分词后无意义的字段建议使用keyword
类型,例如邮箱地址、主机名、商品标签等。
常有参数包含以下
-
analyzer:用来分词,包含索引存储阶段和搜索阶段(其中查询阶段可以被search_analyzer参数覆盖),该参数默认设置为index的analyzer设置或者standard analyzer
-
index:是否可以被搜索到。默认是
true
-
fields:Multi-fields允许同一个字符串值同时被不同的方式索引,例如用不同的analyzer使一个field用来排序和聚类,另一个同样的string用来分析和全文检索。下面会做详细的说明
-
search_analyzer:这个字段用来指定搜索阶段时使用的分词器,默认使用
analyzer
的设置 -
search_quote_analyzer:搜索遇到短语时使用的分词器,默认使用
search_analyzer
的设置
keyword 类型#
-
keyword
用于索引结构化内容(例如电子邮件地址,主机名,状态代码,邮政编码或标签)的字段,这些字段被拆分后不具有意义,所以在es中应索引完整的字段,而不是分词后的结果。 -
通常用于过滤(例如在博客中根据发布状态来查询所有已发布文章),排序和聚合。
keyword
只能按照字段精确搜索,例如根据文章id查询文章详情。如果想根据本字段进行全文检索相关词汇,可以使用text
类型。
日期检测
当 Elasticsearch 遇到一个新的字符串字段时,它会检测这个字段是否包含一个可识别的日期,比如 2014-01-01 。如果它看起来像一个日期,这个字段会被作为 date 类型添加,否则,它会被作为 string 类型添加。
日期检测可以通过在根对象上设置 date_detection 为 false 来关闭:
Elasticsearch 判断字符串为日期的规则可以通过 dynamic_date_formats 配置 来修改。
多字段特性
多字段特性(multi-fields),表示允许对同一字段采用不同的配置,比如分词。
常见例子是对人名实现拼音搜索,只需要在人名中新增一个字段pinyin即可。但是这种方式不是十分优雅,multi-fields可以在不改变整体结构的前提下,增加一个子字段:
put my_index { "mappings":{ "properties":{ "first_name":{ "type":"text", "fields":{ "pinyin":{ "type":"text" } } } } } }