Elasticsearch入门教程(三):Elasticsearch索引&映射

原文: Elasticsearch入门教程(三):Elasticsearch索引&映射

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处连接和本声明。
本文连接: https://blog.csdn.net/vbirdbest/article/details/79213163

索引概念简介

一般说的索引有两种词性,名称和动词。git

  • 动词索引indexing,索引一个文档,表示把一个文档存储到索引Index里,能够用来查询和检索,es采用倒排索引
  • 名词索引index,简单的理解成关系型数据库中的数据库的概念

索引的命名必须是所有小写,不能如下划线开头.github

建立索引

建立索引能够显式建立,也能够隐式建立。算法

  • 显式建立:在关系型数据库中,须要先建数据库,在建立数据库时能够指定一些配置,如字符编码,数据库引擎等,建立表时须要指定表都包含哪些列,每一个列的数据类型等,在在Elasticsearch中建立数据库(索引)和建立表(映射)是一步完成的,显式建立须要在建立时指定对索引的一些配置,须要列举出索引包含的字段,也就是所谓的映射Mapping
  • 隐式操做:隐式操做的方式是直接向索引中插入一条文档便可,es在插入的时候会判断索引是否存在,若是不存在,系统会根据文档包含的字段做为索引的映射,对索引的一些配置采用默认的配置来建立出来索引,建立索引的过程是es在后台默默的实现的。

显式建立能够根据具体状况对索引进行配置,并且对于中文分词es是默认采用的分词是适合英文并适合中文的,能够在建立索引的时候本身指定分词器。sql

ES支持的数据类型

  • text 文本类型,text类型若是不显示指定映射的字段属性,默认是使用标准分词器进行分词,通常数据类型是text要么显示指定分词器,要么不分词,通常不使用默认的分词器(除非文本是纯英文)
  • keyword : 若是数组中的值是字符串,最好使用keyword, 它不会对字符串进行分词
  • date 支持的格式有:能够经过format定义日期的数据格式,也支持毫秒数
  • boolean
  • float
  • double
  • byte
  • short
  • integer
  • long
  • object
  • nested : 嵌套对象, 用于数组中的元素是对象的[{}, {}]
  • ip 即支持ipv4也支持ipv6
  • completion
  • binary
  • geo-point: 支持经纬度存储和距离范围检索
  • geo-shape:支持任意图形范围的检索,例如矩形和平面多边形

注意:不一样的数据类型索引的方式有稍许不一样,如date何text类型不同,date采用精确匹配,text采用全文检索方式。对于数组,es并无专门的数组类型。任何域均可以包含0、1或者多个值,就像全文域分析获得多个词条。这暗示 数组中全部的值必须是相同数据类型的。数据库

映射mappings

映射就是建立索引时指定都包含哪些字段以及字段的数据类型、分词器等一些设置。数组

字段设置参数bash

  • “type”: “text”, // 指定字段的数据类型
  • “analyzer”:”ik _max_word”, //指定分词器的名称,便可用使用内置的分词器也可使用第三方分词器
    • 默认standard,
    • 内置的分析器有whitespace 、 simple和english
    • 第三方分词器:ik分词器 包括ik_max_word和ik_smart,ik_max_word:会将文本作最细粒度的拆分;尽量多的拆分出词语 ,ik_smart:会作最粗粒度的拆分;已被分出的词语将不会再次被其它词语占有
  • “search_analyzer”:”ik _max_word” // 指定查询的分词器,默认和analyzer保持一致,通常分词器和查询分词器要保持一致
  • “properties”: {}, // 当数据类型是object时,须要具体指定内部对象对应的字段
  • “format”: “yyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis” // 格式化,通常用于指定日期类型的格式
  • “dynamic”: “strict” 动态映射配置,当文档中发现新字段时应该如何处理, 能够用在根 object 或任何 object 类型的字段上,你能够将 dynamic 的默认值设置为 strict , 而只在指定的内部对象中开启它
    • true: 默认值,动态添加新的字段
    • false: 忽略新的字段
    • strict: 若是遇到新字段抛出异常,若是Elasticsearch是做为重要的数据存储,可能就会指望遇到新字段就会抛出异常,这样能及时发现问题。
  • dynamic_templates 动态模板:为知足条件的字段作统一映射,能够经过字段名称或者字段类型来匹配指定的映射规则,每一个模板都有一个名称,你能够用来描述这个模板的用途, 一个mapping来指定映射应该怎样使用,以及至少一个参数 (如 match) 来定义这个模板适用于哪一个字段。
    模板按照顺序来检测;第一个匹配的模板会被启用
    • match 参数只匹配字段名称
    • match_mapping_type 容许你应用模板到特定类型的字段上,就像有标准动态映射规则检测的同样
  • “fielddata”:boolean //针对分词字段,参与排序或聚合时能提升性能,默认是false,false是不容许聚合操做的
  • “boost”:1.23 // 权重:字段级别的分数加权,指定字段在搜索时所占的权重,所占的百分比
  • “fields”:{“raw”:{“type”:”keyword”}} //能够对一个字段提供多种索引模式,同一个字段的值,一个分词,一个不分词,应用场景:便可以用于对字符串进行字符排序,也能够全文索引,排序时使用字段.raw来引用排序字段
  • “index”: “analyzed”, // 指定文本类型的字段是否分词、是否存储该字段的值(在新版本中index值为boolean类型,语意也发生了变化,TODO待更新),有三个值:
    • analyzed:首先分析字符串,而后索引(存储)它。换句话说,以全文索引这个域(也就是说即分词,又存储字段的值,便可以经过全文检索的方式对该字段进行搜索)
    • not_analyzed:索引(存储)这个域,因此它可以被搜索,但索引的是精确值。不会对它进行分析(不对字段的值进行分词,而是完整的存储该值,因此只能经过精确值才能搜索出来,即彻底匹配,至关于sql中的等号=的做用)
    • no:不索引这个域。这个域不会被搜索到(对该字段不分词,也不存储,至关于没有这个字段同样???)
  • “store”:false//是否单独设置此字段的是否存储而从_source字段中分离,默认是false,只能搜索,不能获取值
  • “doc_values”:false//对not_analyzed字段,默认都是开启,分词字段不能使用,对排序和聚合能提高较大性能,节约内存
  • “ignore_above”:100 //超过100个字符的文本,将会被忽略,不被索引
  • “include_in_all”:ture//设置是否此字段包含在_all字段中,默认是true,除非index设置成no选项
  • “index_options”:”docs”//4个可选参数docs(索引文档号) ,freqs(文档号+词频),positions(文档号+词频+位置,一般用来距离查询),offsets(文档号+词频+位置+偏移量,一般被使用在高亮字段)分词字段默认是position,其余的默认是docs
  • “norms”:{“enable”:true,”loading”:”lazy”}//分词字段默认配置,不分词字段:默认{“enable”:false},存储长度因子和索引时boost,建议对须要参与评分字段使用 ,会额外增长内存消耗量
  • “null_value”:”NULL”//设置一些缺失字段的初始化值,只有string可使用,分词字段的null值也会被分词
  • “position_increament_gap”:0//影响距离查询或近似查询,能够设置在多值字段的数据上火分词字段上,查询时可指定slop间隔,默认值是100
  • “similarity”:”BM25”//默认是TF/IDF算法,指定一个字段评分策略,仅仅对字符串型和分词类型有效
  • “term_vector”:”no”//默认不存储向量信息,支持参数yes(term存储),with_positions(term+位置),with_offsets(term+偏移量),with_positions_offsets(term+位置+偏移量) 对快速高亮fast vector highlighter能提高性能,但开启又会加大索引体积,不适合大数据量用

ik分词器 https://github.com/medcl/elasticsearch-analysis-ik 支持自定义热词配置(如 香菇 蓝瘦 帅的一逼 等)微信

  
  
  
   
   
            
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
// 默认standard,内置的分析器有whitespace 、 simple 和 english // ik支持两种分词器:ik_max_word,ik_smart // 分析器:用于测试分词的数据 GET /_analyze { "analyzer" : "ik_max_word", "text": "美国留给伊拉克的是个烂摊子吗" }

settings设置

settings用于设置索引的分片数量、副本数量、默认的分词器等,Elasticsearch 提供了优化好的默认配置。 除非你理解这些配置的做用而且知道为何要去修改,不然不要随意修改。markdown

  • “number_of_shards” : 5, // 每一个索引的主分片数,默认值是 5 。这个配置在索引建立后不能修改。
  • “number_of_replicas” : 1, // 每一个主分片的副本数,默认值是 1 。对于活动的索引库,这个配置能够随时修改。
  • “analysis” : { “analyzer” : { “ik” : { “tokenizer” : “ik_ max_word” } } }
  
  
  
   
   
            
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
// 建立只有 一个主分片,没有副本的小索引: PUT /my_temp_index { "settings": { "number_of_shards" : 1, "number_of_replicas" : 0 } } // 用update-index-settings API 动态修改副本数: PUT /my_temp_index/_settings { "number_of_replicas": 1 }

aliases别名

索引别名就像一个快捷方式或软链接,或者是一个指向,都是最终指的同一个东西,别名 带给咱们极大的灵活性,容许咱们作下面这些:app

  • 在运行的集群中能够无缝的从一个索引切换到另外一个索引
  • 给多个索引分组 (例如, last_three_months)
  • 给索引的一个子集建立 视图

有两种方式管理别名: _alias用于单个操做, _aliases用于执行多个原子级操做。

Mapping一旦建立是不容许修改字段的数据类型的,为了防止之后有可能修改索引的状况,刚开始建立索引时最好就为该索引建立一个别名,而后在程序中直接使用别名,而不使用真实的索引名称。
若是后面须要要修改映射,能够再建立一个新的索引,而后把以前索引里的数据导入到新建立的索引里, 为新索引增长一个别名,将别名从老索引中移除,这样应用程序仍然使用的是别名,而这个别名已经指向了新的索引,这样就达到了不修改索引名而修改索引的目的。

  
  
  
   
   
            
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
// 0. 建立索引(age的类型为long) PUT /school_v1 { "mappings": { "students": { "properties": { "name": { "type": "text" }, "age": {"type": "long"} } } } } // 1. 为索引建立一个别名 PUT /school_v1/_alias/school // 查看别名指向的索引 GET /*/_alias/school // 查询索引对应的别名 GET /school_v1/_alias/* // 2.建立一个新的索引,名字不能和以前的不同,此次将age的数据类型改成short PUT /school_v2 { "mappings": { "students": { "properties": { "name": { "type": "text" }, "age": {"type": "short"} } } } } // 3.迁移数据:将以前的索引里的文档迁移到新的索引上 // 先将数据批量查询出来,而后批量插入 GET /school/students/_search?scroll=1m POST /schools/students/_bulk {"index": {"_id": 1}} {"name": "张三","age": 27} {"index": {"_id": 2}} {"name": "小明","age": 28} GET /schools/students/_search // 4.为新索引增长别名,别名名称为老索引名称,这样系统能够直接使用老索引的名称来操做新索引 POST /_aliases { "actions": [ { "add": { "index": "school_v2", "alias": "school"}, "remove": { "index": "school_v1", "alias": "school"} } ] } GET /school/students/_search

别名就是索引的另外一个名字,就像人的姓名和笔名同样,都是指向的同一我的,能够经过POST /_aliases 路径对别名进行add、remove操做

TIP: 在你的应用中使用别名而不是索引名。而后你就能够在任什么时候候重建索引。别名的开销很小,应该普遍使用。

索引操做

建立索引
PUT /{index}

  
  
  
   
   
            
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
// 注意:当前建立的索引的动态映射配置根对象是不容许添加新字段的,动态映射类型为严格类型,可是内部对象是容许添加新字段的 PUT /shop_v1 { "aliases": { "shop": {} }, "settings" : { "number_of_shards" : 5, "number_of_replicas" : 1, "refresh_interval": "1s", "analysis" : { "analyzer" : { "ik" : { "tokenizer" : "ik_max_word" } } } }, "mappings": { "goods": { "dynamic": "strict", "dynamic_templates":[ { "date": { "match": "*_date", "match_mapping_type": "date", "mapping": { "type": "date", "format": "yyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis" } }}, { "ik": { "match": "*", "match_mapping_type": "string", "mapping": { "type": "text", "analyzer": "ik_max_word", "search_analyzer": "ik_max_word" } }} ], "properties": { "name": { "type": "text", "analyzer": "ik_max_word", "search_analyzer": "ik_max_word" }, "price": { "type": "double" }, "quantity": { "type": "integer" }, "colors": { "type": "keyword" }, "is_discount": { "type": "boolean" }, "create_date": { "type": "date", "format": "yyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis" }, "ip_addr": { "type": "ip" }, "location": { "type": "geo_point", "lat_lon": true }, "merchant": { "type": "object", "dynamic": true, "properties": { "id": { "type": "long" }, "shop_name": { "type": "text" } } }, "cpu": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } } } } } }

refresh_interval:索引刷新时间间隔,一个持续时间值, 例如 1s(1 秒) 或 2m(2 分钟)。 一个绝对值1表示的是1毫秒 –无疑会使你的集群陷入瘫痪, -1:表示关闭刷新, 默认为一秒,若是索引了一个文档而后当即尝试搜索它,但却没有搜到,多是尚未到间隔时间,尚未刷新

  • 查看全部索引 GET /_cat/indices?v&pretty

  • 查看某个索引 GET /{index}

  • 删除索引单个索引 DELETE /{index}

  • 删除全部索引 DELETE /_all 或者 DELETE /*

  • 删除多个索引: DELETE /index1,index2 或者 DELETE /index*

  • 查看索引的映射 GET /{index}/_mapping

  • 查看某个索引的某个类型的映射 GET /{index}/_mapping/{type}

  • 映射添加新字段 PUT /{index}/_mapping/{type}

  
  
  
   
   
            
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
PUT /shop/_mapping/goods { "properties": { "params": { "type": "nested", "properties": { "id": { "type": "long" }, "label": { "type": "text" }, "value": { "type": "text" } } } } }
  
  
  
   
   
            
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
// 插入一条文档 POST /shop/goods { "name": "【特别尺码】女装 棉混纺休闲针织衫(长袖) 407767 优衣库UNIQLO", "price": 149.00, "quantity": 100, "colors": ["乳白色", "红色", "黄色"], "is_discount": true, "create_date": "2018-01-31 12:10:30", "ip_addr": "192.168.1.1", "location": "41.12,-71.34", "merchant": { "id": 1111, "shop_name": "优衣库官方旗舰店" }, "params": [ {"id": 1, "label":"货号", "value": "7525001123"}, {"id": 2, "label":"品牌", "value": "Cache Cache"} ] }

查询文档 /{index}/{type}/_search

  
  
  
   
   
            
   
   
  • 1
GET /shop/goods/_search

修改索引

  • 新增字段
  • 修改字段的数据类型
  
  
  
   
   
            
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
``` // 建立索引 PUT /school { "mappings": { "students": { "properties": { "name": { "type": "text" }, "age": {"type": "long"} } } } } // 插入一条文档 PUT /school/students/1 { "name": "张三", "age": 27 } // 查询映射 GET school/_mapping/students // 添加文档,增长一个新字段height身高 PUT /school/students/2 { "name": "小明", "age": 28, "height": 1.80 } GET school/_mapping/students // 查看映射能够看到自动将height做为float类型添加到映射里面 "height": {"type": "float"}

从新索引

尽管能够增长新的类型到索引中,或者增长新的字段到类型中,可是不能添加新的分析器或者对现有的字段作改动。 若是你那么作的话,结果就是那些已经被索引的数据就不正确, 搜索也不能正常工做。

对现有数据的这类改变最简单的办法就是从新索引:用新的设置建立新的索引并把文档从旧的索引复制到新的索引。

为了有效的从新索引全部在旧的索引中的文档,用 scroll 从旧的索引检索批量文档 , 而后用 bulk API 把文档推送到新的索引中。

同时并行运行多个重建索引任务,可是你显然不但愿结果有重叠。正确的作法是按日期或者时间 这样的字段做为过滤条件把大的重建索引分红小的任务:

  
  
  
   
   
            
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
GET /old_index/_search?scroll=1m { "query": { "range": { "date": { "gte": "2014-01-01", "lt": "2014-02-01" } } }, "sort": ["_doc"], "size": 1000 }

若是旧的索引持续会有变化,你但愿新的索引中也包括那些新加的文档。那就能够对新加的文档作从新索引, 但仍是要用日期类字段过滤来匹配那些新加的文档。

经过建立新的索引,将数据从新迁移到新索引中,这种变相的更改索引的配置的方式的缺点是改变了原索引的名称(索引名称不容许重复,新索引就要使用新的索引名)。

注意

  • 禁用_all或者通配符,防止误操做
    对一些人来讲,可以用单个命令来删除全部数据可能会致使可怕的后果。若是你想要避免意外的大量删除, 你能够在你的 elasticsearch.yml 作以下配置:action.destructive_requires_name: true
    这个设置使删除只限于特定名称指向的数据, 而不容许经过指定 _all 或通配符来删除指定索引库。你一样能够经过 Cluster State API 动态的更新这个设置。

个人微信公众号:

相关文章
相关标签/搜索