赞
踩
什么是Mapping?**Mapping定义了索引中的文档有哪些字段及其类型、这些字段是如何存储和索引的。**每个文档都是一个字段的集合,每个字段都有自己的数据类型,例如我们定义的books索引,其中有book_id、name等字段。所以Mapping的作用有:
PUT books
{
"mappings": {
"properties": {
"book_id": {
"type": "keyword"
},
"name": {
"type": "text",
"analyzer": "standard"
}
}
}
}
如上示例是我们定义了一个索引的Mapping例子,可以看到book_id的类型为keyword,而name的类型为text,并且name字段指定了分词器为standard
我们本篇的内容主要分为以下几点:
除了预先定义好Mapping外,如果写入文档时索引不存在的时候会自动创建索引,或者写入的字段不存在也会自动创建这个字段,官方把这个功能称之为 Dynamic Mapping。
动态索引的好处是使得我们无需手动定义Mapping,ES帮我们根据文档的信息自动推算出各个字段的信息。但是啊,推算的东西不一定准确的,很多时候并不是我们想要的东西。所以还是尽量自定义Mapping
# 在不存在的索引中写入一个文档 PUT test_mapping/_doc/1 { "name": "es", "count": 1 } # 使用下面指令查看其 Mapping 的结果 GET test_mapping/_mapping # Dynamic Mapping 产生的 Mapping 结果 { "test_mapping" : { "mappings" : { "properties" : { "count" : { "type" : "long" }, "name" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } } } } } }
Dynamic Mapping的功能可以自动推断字段的类型,这些类型都是ES支持的基本类型,这些类型主要有:
在7.x之后的版本中,字符串类型只有keyword和text两种,旧版本的string类型不再支持
我们知道JSON是没有热情类型的,所以其形式可以如下表示
实际上,在底层ES都会把日期类型转换为UTC,并且作为毫秒形式的时间戳用一个long来存储
数字类型分为byte、short、integer、long、float、double、half_float、scaled_float、unsigned_long
在需求满足的条件下,应当选择尽可能小的数据类型,除了可能会减少存储空间外,也会提高索引数据和检索数据的效率
我们的数据很多时候都需要用到数组和对象、嵌套类型等复杂数据类型来表示的,例如书本作者可以有多个,这个作者字段就需要保存为一个数组。
下面来介绍一下对象和数组,至于嵌套对象,后面会讲
JSON中是可以嵌套对象的,保存对象类型可以用object类型,但实际上在ES中会讲原JSON文档扁平化存储的,加入作者字段是一个对象,那么可以表示为:
{
"author": {
"first":"zhang",
"last":"san"
}
}
实际在存储的时候,ES在存储的时候会转换为以下格式:
{
"author.first": "zhang",
"author.last": "san"
}
对于数组来说,ES并没有定义关键字来表示一个字段为数组类型。默认情况下,**任何一个字段都可以包含0个或多个值,只需要这些值是相同的数据类型。**所以我们在创建数据的时候可以直接写入数组类型:
PUT books/_doc/3
{
"author": ["Neil Matthew","Richard Stones"],
}
前面我们提到最好不要用Dynamic Mapping来生成Mapping,但是如果Mapping拥有的字段非常多的时候,自定义Mapping是非常痛苦的并且容易出错。那有没有办法减轻一下我们的工作量哪?
我们可以把JSON对象直接写入,利用Dynamic Mapping的特性帮我们生成一个初步可用的Mapping,然后我们修改这个 Mapping来直到满足我们的需求。
大概的步骤如下:
我们在使用Dynamic Mapping的时候,JSON文档的字段类似会自动转换为ES的类型,下面是对照表:
Mapping参数可以用来控制某个字段的特性。例如这个字段是否被索引、用什么分词器、空值是否可以被搜索到等。Mapping提供的参数有很多,我们看看常见的几个:index、analyzer、dynamic、null_value、copy_to
当某个字段不想被索引或者查询的时候,可以用index参数来进行控制,其接受的值为true或者false。使用示例如下:
PUT index_param_index
{
"mappings": {
"properties": {
"name": {
"type": "text",
"index": false # name 字段不进行索引操作
},
"address": { "type": "text" }
}
}
}
这个参数其实我们用过多次了,它是用来指定使用哪个分词器的
当我们进行全文本搜索的时候,会将检索的内容先进行分词,然后在进行匹配。默认情况下,检索的内容使用的分词器和与字段指定的分词器是一致的,但如果设置了search_analyzer,检索内容使用的分词器将与search_analyzer设定的一致。其使用示例如下:
PUT analyzer_index
{
"mappings": {
"properties": {
"name": {
"type": "text",
"analyzer": "simple",
"search_analyzer": "standard"
}
}
}
}
可以在文档和对象级别对Dynamic Mapping进行控制,刚刚在Dynamic Mapping一节的内容中介绍过dynamic属性对文档级别的影响了,现在结合文档和对象级别来一个示例:
PUT dynamic_index { "mappings": { "dynamic": "strict", # 1,文档级别,表示文档不能动态添加 top 级别的字段 "properties": { "author": { # 2,author 对象继承了文档级别的设置。 "properties": { "address": { "dynamic": "true", # 3,表示 address 对象可以动态添加字段 "properties":{} }, "country": { "properties":{} } } } } } }
如果需要对null值实现搜索的时候,需要设置字段的null_value参数。null_value参数默认值为null,其允许用户使用指定值替换控制,以便它可以索引和搜索
需要注意的是,**null_value只决定数据是如何索引的,不影响_source的内容,并且null_value的值的类型需要与字段的类型一致。**例如一个long字段的字段,其null_value的值不能为空字符串。使用“NULL”显示值来代替null,使用示例如下:
# 创建索引 PUT null_value_index { "mappings": { "properties": { "id": { "type": "keyword" }, "email": { "type": "keyword", "null_value": "NULL" # 使用 "NULL" 显式值 } } } } # 插入数据 PUT null_value_index/_doc/1 { "id": "1", "email": null } # 查询空值数据 GET null_value_index/_search { "query": { "term": { "email": "NULL" } # 使用显式值来查询空值的文档 } }
copy_to参数允许用户复制多个字段的值到目标字段,这个字段可以像单个字段那样呗查询。其示例如下:
# 创建索引 PUT users { "mappings": { "properties": { "first_name": { "type": "text", "copy_to": "full_name" }, "last_name": { "type": "text", "copy_to": "full_name" }, "full_name": { "type": "text" } } } } # 插入数据 PUT users/_doc/1 { "first_name": "zhang", "last_name": "san" } # 查询 GET users/_search { "query": { "match": { "full_name": { "query": "zhang san", "operator": "and" } } } } # 结果 { "hits" : { "hits" : [ { "_source" : { "first_name" : "zhang", "last_name" : "san" } } ] } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。