03-Elasticsearch API - 索引管理及映射

获取索引的mapping

GET [/{type}[/type]]/_mapping

实例:

//获取整个库的mapping
GET /_mapping

//获取website的所有mapping
GET /website/_mapping

//获取website中blog类型的mapping
GET /website/blog/_mapping

测试分析器

GET /_analyze
{
  "analyzer": "standard",
  "text": "Text to analyze"
}

//result
{
  "tokens": [
    {
      "token": "text",
      "start_offset": 0,
      "end_offset": 4,
      "type": "<ALPHANUM>",
      "position": 0
    },
    {
      "token": "to",
      "start_offset": 5,
      "end_offset": 7,
      "type": "<ALPHANUM>",
      "position": 1
    },
    {
      "token": "analyze",
      "start_offset": 8,
      "end_offset": 15,
      "type": "<ALPHANUM>",
      "position": 2
    }
  ]
}

创建一个索引

到目前为止, 我们已经通过索引一篇文档创建了一个新的索引 。这个索引采用的是默认的配置,新的字段通过动态映射的方式被添加到类型映射。现在我们需要对这个建立索引的过程做更多的控制:我们想要确保这个索引有数量适中的主分片,并且在我们索引任何数据 之前 ,分析器和映射已经被建立好。

为了达到这个目的,我们需要手动创建索引,在请求体里面传入设置或类型映射,如下所示:

PUT /my_index
{
    "settings": { ... any settings ... },
    "mappings": {
        "type_one": { ... any mappings ... },
        "type_two": { ... any mappings ... },
        ...
    }
}

如果你想禁止自动创建索引,你 可以通过在 config/elasticsearch.yml 的每个节点下添加下面的配置:

action.auto_create_index: false

删除索引

//删除一个
DELETE /my_index
//删除多个
DELETE /index_one,index_two
//通过通配符删除多个
DELETE /index_*
//删除所有的索引
DELETE /_all
DELETE /*

对一些人来说,能够用单个命令来删除所有数据可能会导致可怕的后果。如果你想要避免意外的大量删除, 你可以在你的 elasticsearch.yml 做如下配置:

action.destructive_requires_name: true

这个设置使删除只限于特定名称指向的数据, 而不允许通过指定 _all 或通配符来删除指定索引库。

设置索引

PUT /{index}
{
   "settings" : {
      //两个重要的设置项
      "number_of_shards" : 5,  //主分片数量
      "number_of_replicas" : 1 //复制分片份数
   }
}

实例:

PUT /blogs
{
   "settings" : {
      "number_of_shards" : 3,
      "number_of_replicas" : 1
   }
}

//result
{
  "acknowledged": true,
  "shards_acknowledged": true
}

主分片的的作用是将数据集进行拆分,当数据量大时可以存放在不同的机器上,且一个分片是一个lucene实例,所以分配多个分片在一定程度上也可提高并发搜索效率。主分片数创建索引时就确定了,后面不能修改,复制分片数可以后期动态修改

动态修改设置项

PUT /{index}/_settings
{
  "field": value,
  ...
}

实例:

//修改复制分片
PUT /blogs/_settings
{
   "number_of_replicas" : 2
}

//result
{
  "acknowledged": true
}

创建自定义分析器

虽然Elasticsearch带有一些现成的分析器,然而在分析器上Elasticsearch真正的强大之处在于,你可以通过在一个适合你的特定数据的设置之中组合字符过滤器、分词器、词汇单元过滤器来创建自定义的分析器。
一个 分析器 就是在一个包里面组合了三种函数的一个包装器, 三种函数按照顺序被执行:

字符过滤器
字符过滤器 用来 整理 一个尚未被分词的字符串。例如,如果我们的文本是HTML格式的,它会包含像 <p> 或者 <div> 这样的HTML标签,这些标签是我们不想索引的。我们可以使用 html清除 字符过滤器 来移除掉所有的HTML标签,并且像把 Á 转换为相对应的Unicode字符 Á 这样,转换HTML实体。

一个分析器可能有0个或者多个字符过滤器。

分词器
一个分析器 必须 有一个唯一的分词器。 分词器把字符串分解成单个词条或者词汇单元。 标准 分析器里使用的 标准 分词器 把一个字符串根据单词边界分解成单个词条,并且移除掉大部分的标点符号,然而还有其他不同行为的分词器存在。

例如, 关键词 分词器 完整地输出 接收到的同样的字符串,并不做任何分词。 空格 分词器 只根据空格分割文本 。 正则 分词器 根据匹配正则表达式来分割文本 。

词单元过滤器
经过分词,作为结果的 词单元流 会按照指定的顺序通过指定的词单元过滤器 。

词单元过滤器可以修改、添加或者移除词单元。我们已经提到过 lowercase 和 stop 词过滤器 ,但是在 Elasticsearch 里面还有很多可供选择的词单元过滤器。 词干过滤器 把单词 遏制 为 词干。 ascii_folding 过滤器移除变音符,把一个像 "très" 这样的词转换为 "tres" 。 ngram 和 edge_ngram 词单元过滤器 可以产生 适合用于部分匹配或者自动补全的词单元。

PUT /my_index
{
    "settings": {
        "analysis": {
            "char_filter": { ... custom character filters ... },
            "tokenizer":   { ...    custom tokenizers     ... },
            "filter":      { ...   custom token filters   ... },
            "analyzer":    { ...    custom analyzers      ... }
        }
    }
}

实例:

//此处自定的组件都只能在my_index索引中使用,对其他索引时不可见的
PUT /my_index
{
    "settings": {
        "analysis": {
            //自定义字符过滤器:将&转换为and
            "char_filter": {
                "&_to_and": {
                    "type":       "mapping",
                    "mappings": [ "&=> and "]
            }},
            //自定义此单元过滤器:设置the和a为停用词
            "filter": {
                "my_stopwords": {
                    "type":       "stop",
                    "stopwords": [ "the", "a" ]
            }},
            //自定义分析器:组合上面的自定义字符过滤器与词单元过滤器
            "analyzer": {
                "my_analyzer": {
                    "type":         "custom",
                    "char_filter":  [ "html_strip", "&_to_and" ],
                    "tokenizer":    "standard",
                    "filter":       [ "lowercase", "my_stopwords" ]
            }}
}}}

// 测试自定义分析器
GET /my_index/_analyze
{
  "analyzer": "my_analyzer",
  "text": "The quick & brown fox"
}

对象映射

根对象
映射的最高一层被称为 根对象 ,它可能包含下面几项:
一个 properties 节点,列出了文档中可能包含的每个字段的映射
各种元数据字段,它们都以一个下划线开头,例如 _type 、 _id 和 _source
设置项,控制如何动态处理新的字段,例如 analyzer 、 dynamic_date_formats 和 dynamic_templates
其他设置,可以同时应用在根对象和其他 object 类型的字段上,例如 enabled 、 dynamic 和 include_in_all
对象属性
文档字段属性的三个重要设置:
type
字段的数据类型,ES支持的核心简单域类型如下:
字符串:text、keyword(ES5之前为string,ES5之后,将string类型被分成Text和Keyword两种类型,keyword类型的数据只能完全匹配,适合那些不需要分词的数据,对过滤、聚合非常友好,text当然就是全文检索需要分词的字段类型了。将类型分开的好处就是使用起来更加简单清晰,以前需要设置analyzer和index,并且有很多都是自定义的分词器,从名称根本看不出来到底分词没有,用起来很麻烦。 )
整数:byte、short、integer、long
浮点数:float、double
布尔型:boolean
日期型:date
以及数组、嵌套对象(嵌套对象如何索引)、ip、geo_point、geo_shape等
index
字段是否应当被当成全文来搜索( analyzed ),或被当成一个准确的值( not_analyzed ),还是完全不可被搜索( no )
analyzer
确定在索引和搜索时全文字段使用的 analyzer
实例:

PUT /gb 
{
  "mappings": {
    "tweet" : {
      "properties" : {
        "tweet" : {
          "type" :    "text",
          "analyzer": "english",  //使用英文分词器
          "fields": { //当我们对一个字段分词与不分词都需要时,就可添加fields来实现
              "keyword": {
                "type": "keyword"
              }
            }
        },
        "date" : {
          "type" :   "date"
        },
        "name" : {
          "type" :   "text"
        },
        "user_type": {
          "type" :   "keyword"
        },
        "desc": {
          "type" :   "keyword",
          "index": "no" //不进行索引
        },
        "user_id" : {
          "type" :   "long"
        }
      }
    }
  }
}

** 修改映射 **
已经存在的数据不能修改映射类型,因为修改后新数据与老数据不一致,这样会导致数据混乱,但我们可以为新增字段添加映射类型

//如添加一个test字段
PUT /gb/tweet/_mapping
{
    "properties": {
        "test":{"type": "keyword"}
    }
}

元数据:_all字段
一个把其它字段值 当作一个大字符串来索引的特殊字段。 query_string 查询子句(搜索 ?q=john )在没有指定字段时默认使用 _all 字段。

//对_all字段进行搜索
GET /_search
{
    "match": {
        "_all": "john smith marketing"
    }
}

如果你不再需要 _all 字段,你可以通过下面的映射来禁用:

PUT /my_index/_mapping/my_type
{
    "my_type": {
        "_all": { "enabled": false }
    }
}

在映射api中我们也可以通过每个字段的属性include_in_all来设置自己是否包含在_all字段中,默认为true。在一个对象(或根对象)上设置 include_in_all 可以修改这个对象中的所有字段的默认行为。
元数据:文档标识
文档标识与四个元数据字段 相关:
_id 文档的 ID 字符串
_type 文档的类型名
_index 文档所在的索引
_uid _type 和 _id 连接在一起构造成 type#id
默认情况下, _uid 字段是被存储(可取回)和索引(可搜索)的。 _type 字段被索引但是没有存储, _id 和 _index 字段则既没有被索引也没有被存储,这意味着它们并不是真实存在的。
尽管如此,你仍然可以像真实字段一样查询 _id 字段。Elasticsearch 使用 _uid 字段来派生出 _id 。 虽然你可以修改这些字段的 index 和 store 设置,但是基本上不需要这么做。

动态映射

默认情况下,当 Elasticsearch 遇到文档中以前 未遇到的字段,它用 dynamic mapping 来确定字段的数据类型并自动把新的字段添加到类型映射。我们可以通过dynamic属性来控制新字段的行为:
true 动态添加新的字段--缺省
false 忽略新的字段
strict 如果遇到新字段抛出异常
实例:

PUT /my_index
{
    "mappings": {
        "my_type": {
            "dynamic":      "strict",  //根对象索引新字段会抛出异常
            "properties": {
                "title":  { "type": "string"},
                "stash":  {
                    "type":     "object",
                    "dynamic":  true //内嵌对象可以动态索引新字段
                }
            }
        }
    }
}

自定义动态映射

** 日期检测**
当 Elasticsearch 遇到一个新的字符串字段时,它会检测这个字段是否包含一个可识别的日期,比如 2014-01-01 。 如果它像日期,这个字段就会被作为 date 类型添加。否则,它会被作为 string 类型添加。若我们想禁用这种行为,让其默认添加为string类型,可将date_detection 设置为false,关闭日期格式检测。
实例:

PUT /my_index
{
    "mappings": {
        "my_type": {
            "date_detection": false
        }
    }
}

** 动态模板**
我们可以通过dynamic_templates来控制新检测生成字段的映射。
实例:

PUT /my_index
{
    "mappings": {
        "my_type": {
            "dynamic_templates": [ //遇到新字段从上往下匹配模式
                { "es": {
                      "match":              "*_es", //匹配字段名以 _es 结尾的字段
                      "match_mapping_type": "string",
                      "mapping": {
                          "type":           "string",
                          "analyzer":       "spanish"
                      }
                }},
                { "en": {
                      "match":              "*", //匹配其他所有字符串类型字段
                      "match_mapping_type": "string",
                      "mapping": {
                          "type":           "string",
                          "analyzer":       "english"
                      }
                }}
            ]
}}}

match_mapping_type 允许你应用模板到特定类型的字段上,就像有标准动态映射规则检测的一样, (例如 string 或 long)。

match 参数只匹配字段名称, path_match 参数匹配字段在对象上的完整路径,所以 address.*.name 将匹配这样的字段:

{
    "address": {
        "city": {
            "name": "New York"
        }
    }
}

unmatch 和 path_unmatch将被用于未被匹配的字段。

缺省映射

通常,一个索引中的所有类型共享相同的字段和设置。 default 映射更加方便地指定通用设置,而不是每次创建新类型时都要重复设置。 default 映射是新类型的模板。在设置 default 映射之后创建的所有类型都将应用这些缺省的设置,除非类型在自己的映射中明确覆盖这些设置。
实例:

PUT /my_index
{
    "mappings": {
        "_default_": {
            //在该索引中默认禁用所有类型的_all字段
            "_all": { "enabled":  false },
            //以time结尾的字段都映射成date类型
            "dynamic_templates": [ 
                { "time": {
                      "match":              "*time", 
                      "match_mapping_type": "string",
                      "mapping": {
                          "type":           "date"
                      }
                }},
             ]
        },
        "blog": {
            //覆盖默认设置
            "_all": { "enabled":  true  }
        }
    }
}

重新索引数据

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

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

字段 _source 的一个优点是在Elasticsearch中已经有整个文档。你不必从源数据中重建索引,而且那样通常比较慢。

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

索引别名与零停机

在前面提到的,重建索引的问题是必须更新应用中的索引名称。 索引别名就是用来解决这个问题的!
索引 别名 就像一个快捷方式或软连接,可以指向一个或多个索引,也可以给任何一个需要索引名的API来使用。别名 带给我们极大的灵活性,允许我们做下面这些:
在运行的集群中可以无缝的从一个索引切换到另一个索引
给多个索引分组 (例如, last_three_months)
给索引的一个子集创建 视图
有两种方式管理别名: _alias 用于单个操作, _aliases 用于执行多个原子级操作。
实例:

PUT /my_index_v1 
//设置别名
PUT /my_index_v1/_alias/my_index
//查看别名执行那个索引
GET /*/_alias/my_index
//查看索引有那个别名
GET /my_index_v1/_alias/*
//原子操作执行别名删除与添加
POST /_aliases
{
    "actions": [
        { "remove": { "index": "my_index_v1", "alias": "my_index" }},
        { "add":    { "index": "my_index_v2", "alias": "my_index" }}
    ]
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容