(八)类型映射详解

前言

通过前面章节的学习,我们已经可以让elasticsearch对中文分词有比较好的效果了,就是使用IK分词器,但我们也知道,elasticsearch的默认分词器是standard分词器,那如何把standard分词器切换到IK分词器呢?
我们在讲解elasticsearch的重要概念的时候我们提到了一个概念:type(类型),为了更好的理解该概念,我们还拿了关系型数据库的表来跟type对比,因为他们不管是思想上还是概念上都是很相似的。
在使用关系型数据库时,我们是必须事先确定好数据表结构(schema),给该表中的每个字段规定其存储的数据类型和数据长度,是否能为空等等的约束,确定好后才能创建该表。但是大家回想之前我们在学RESTful API的时候,我们很简单的就完成了一个文档的新增操作了PUT /store/employee/1,并没有事先规定好类似关系型数据库表的约束,那么既然elasticsearch中的type跟表很相似,为什么我们新增一个文档的时候,就可以直接就录入文档呢?其实并不是没有事先规定约束的,我们当时还补充了录入这个文档的执行过程:先查找名字叫store的索引(index),如果没有,则创建该索引。然后查找名字叫employee的文档类型(type),如果没有,则创建该文档类型。最后查找id为1的员工,如果没有则相当于新建一个员工文档,并设置员工id为1,如果有,则相当于更新员工id为1的文档数据。这里的文档字段类型由elasticsearch帮我们完成自动匹配,当然我们也可以自定义文档的各个字段内容的数据类型和其他的一些约束。当时我们是这样说的,所以,并不是没有规定好约束,而是如果我们没有指定它的约束的话,elasticsearch就自动为我们创建好约束了。
在elasticsearch中,这些约束有个专业术语,叫做mapping(映射),类似关系型数据库的schema。那这样我们就明白了我们想要使用IK分词器来给我们的中文文档分词,就需要自己来给类型的字段指定映射,这些映射应该包含字段的数据类型、数据长度、使用分词器等等的约束。那接下来我们来学习一下elasticsearch的类型映射。

类型映射详解

查看文档类型映射

我们可以使用elasticsearch查看类型的API来查看指定文档的类型:
GET /索引名/_mapping/类型名

文档类型

通过该API得出的结果,我们可以得到以下的信息:索引、映射、类型、字段,在字段下,又有各种给该字段做约束的信息,所有的信息组合起来,就是我们所说的类型映射了(mapping)。employee的这些类型映射我们之前并没有给它设置,是elasticsearch自动判断我们的数据类型,并给这些数据类型设置默认的映射,那这各个字段分别代表什么意思呢?这就是我们接下来要学习的内容了。

字段数据类型

我们先来看看elasticsearch对文档的数据做了哪些类型的区分:

  • 字符串类型:string(3.x后改成了text类型)
  • 整数 : byte,short,integer,long
  • 浮点数:float,double
  • 布尔型: boolean
  • 日期: date
    接着我们来看看这些数据类型有什么约束条件。

约束条件

  • type:指定该字段的数据类型,值为上述列出的“字段数据类型”,不指定的话,由elasticsearch自动判断。
  • index:指定该字段是否索引,接收值为true和false,字符串类型默认为true,其他的数据类型默认为false。值为true的话会做分词。值为false的话不分词,原样写入索引中。
  • ignore_above:接受整数值,如果字符串长度长于这个值,则不写入索引,不指定的话默认为0。
  • analyzer:如果该字段需要索引的话,指定索引时使用的分词器,不指定的话默认使用标准分词器分词。
  • search_analyzer:指定搜索时使用的分词器,不知道的话使用标准分词器分词。
  • store:值为yes和no,默认为no。指定是否将该字段的原始文档写入索引。在elasticsearch中,因为_source中(_source下面解析)已经存储了一份原始文档,在索引中再存储原始文档就多余了,所以Elasticsearch默认是把store属性设置为no。
  • include_in_all:指定该字段是否需要包含在_all中(_all下面解析),接收值为true和false,默认为flase。
  • null_value:如果该字段的值为null,则用该值代替。
  • format:格式化日期类型,比如:yyyy-MM-dd HH:mm:ss||yyyy-MM-dd。默认strict_date_optional_time||epoch_millis

元数据类型

每一个文档都有与之关联的元数据,元数据字段是为了保证系统正常运行内置字段,比如_index表示索引字段,_type表示类型,_id表示文档主键,这些字段都是以下划线开始的,除了这些元数据之外,还有两个很重要的元数据,它们是_all和_source,这两个元数据字段可以在我们创建类型映射的时候,指定约束条件,我们接着来看看:

  • _source:存储的文档的原始值。默认_source字段是开启的,也可以关闭,在什么情况下可以关闭呢?比如某个字段内容非常多,业务里面只需要能对该字段进行搜索,最后返回文档id,查看文档详细内容是用id再次到mysql或者hbase中取数据,把大字段的内容存在Elasticsearch中只会增大索引,如果一条文档节省几KB,放大到亿万级的量结果也是非常可观的。
    如果想要关闭_source字段,在mapping中的设置如下:
{
    "yourtype":{
        "_source":{
            "enabled":false
        },
        "properties": {
            ... 
        }
    }
}

如果只想存储某几个字段的原始值到elasticsearch,可以通过incudes参数来设置,在mapping中的设置如下:

{
    "yourtype":{
        "_source":{
            "includes":["field1","field2"]
        },
        "properties": {
            ... 
        }
    }
}

同样,可以通过excludes参数排除某些字段:

{
    "yourtype":{
        "_source":{
            "excludes":["field1","field2"]
        },
        "properties": {
            ... 
        }
    }
}
  • _all:包含全部内容的字段,默认是关闭的,如果要开启_all字段,索引增大是不言而喻的。_all字段开启适用于不指定搜索某一个字段,根据关键词,搜索整个文档内容。
    开启_all字段的方法和_source类似,mapping中的配置如下:
{
   "yourtype": {
      "_all": {
         "enabled": true
      },
      "properties": {
            ... 
      }
   }
}

也可以通过在字段中指定某个字段是否包含在_all中:

{
   "yourtype": {
      "properties": {
         "field1": {
             "type": "string",
             "include_in_all": false
          },
          "field2": {
             "type": "string",
             "include_in_all": true
          }
      }
   }
}

最后,我们可以通过一张分析图来看看_all和_source在elasticsearch中起到的作用:


_source、_all图解

那到现在,我们已经把类型映射的数据类型、约束条件和元数据指定都了解了,接下来我们就可以对之前创建的employee类型指定约束条件了。

创建类型映射(mapping)

自定义employee类型映射

那接下来我们就要给employee类型做映射了,但是由于之前employee已经有一个elasticsearch创建的默认映射,而elasticsearch没有提供类似修改类型映射的功能,所以我们只能先把整个index删除掉,然后在新建一个index,并且在添加文档前做好employee类型映射。
注意:一般来说index是不能随便删除的,如果真的需要删除,那就要先备份数据,因为我们现在的数据都是测试数据,所以就不备份了,后面我们再来讲讲elasticsearch的数据备份操作
1、删除index
先把原先的store索引删除掉,使用以下DSL语法:
DELETE http://ip:port/my_index

删除索引

看到acknowledged为true,说明删除成功!
2、创建index
重新创建store索引,使用以下DSL语法:
PUT http://ip:port/my_index
创建索引

看到上图右边的窗口打印信息说明索引创建成功!
3、创建类型映射
创建employee类型映射,使用以下DSL语法:

PUT http://ip:port/my_index/my_type/_mapping
{
    "my_type": {
        "properties": {
            "my_field1": {
                "type": "text",
                "index":"true",
                "analyzer":"ik_max_word",
                "search_analyzer":"ik_max_word"
            },
            "my_field2": {
                ...
            },
            ...
        }
    }

}

语法解析:对my_index这个索引中的my_type文档类型创建一个自定义mapping映射,properties块就是my_type文档类型的字段。其中以my_field1这个字段举例,该字段的数据类型为“text”,index为需要分词,索引使用的分词组件为IK分词器,并且是最大分词,搜索同样使用IK分词器,并且是最大分词,其他没有指定的约束,使用默认的值。

创建映射

看到acknowledged为true的答应信息说明我们的employee文档类型约束已经创建好了,我给该文档类型3个字段做了约束,分别是name、age和about,其中name和about都是是text数据类型,需要分词,索引和搜索都使用ik_max_word分词,age是integer数据类型,不需要分词。
我们再使用查看类型映射的API测试一下,看看刚刚创建的类型映射是否生效:
查看类型映射

那通过我们上述的请求发现,我们的employee类型映射已经生效了,已经不是之前那个elasticsearch给我们创建的默认映射了。

添加文档

接下来我们在新的employee类型映射下添加文档:


新增文档

我从新添加了一份id为1的employee文档,但是我这份文档有4个字段,name、age、about和intersect,其中name、age和about是做了映射的,intersect没有做映射,那么elasticsearch就会自动判断intersect字段的数据类型,并且给他设置一些默认的约束。我们可以再来查看一下employee的类型映射有没有发生什么变化:


查看类型映射

通过上述查看employee类型映射我们发现,它此时多了intersect字段的映射,而且约束条件都是默认的,说明如果我们添加的文档某些字段没有事先做映射,那么elasticsearch会为我们这些字段创建映射。

搜索

根据我们前面章节的学习,我们知道在添加文档的时候,首先需要对文档进行索引,索引的第一个环节就是对文档分词,而我们刚刚已经在类型映射中,指定了文档分词的组件使用IK中文分词了,并且重新添加了文档,那这样的话,现在索引库中保存的词元就不再是一个一个的中文字符了,而是有语义的中文词语,最后我们来搜索效果。
先来看看搜索一个没有意义的字符:


搜索“中”

我们可以看到,搜索“中”字符已经不会出来结果了,因为“中”字符单独存在没有什么意义,那接下来我们搜索“中国”看看:


搜索“中国”

搜索“中国”能出来结果,并且我们通过高亮显示可以知道,它是匹配到“中国”这个词元的。
那到现在,我们就通过这个章节的学习,了解了elasticsearch的数据类型、字段约束条件和类型映射这几个知识点了,并且通过自定义的类型映射来实现了中文语义搜索。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,992评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,212评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,535评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,197评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,310评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,383评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,409评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,191评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,621评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,910评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,084评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,763评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,403评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,083评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,318评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,946评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,967评论 2 351

推荐阅读更多精彩内容