1. 程式人生 > 其它 >elasticsearch中索引的管理

elasticsearch中索引的管理

索引管理

我們看到es讓開發一個新的應用變得簡單,不需要任何預先計劃和設定,不過要不了多久
你就會開始想要優化索引和搜尋過程,以便更好的適合您的特定用例,這些定製圍繞著索引和型別的方方面面
本章介紹管理索引和型別對映的API以及一些重要的設定

建立一個索引

  1. 簡單建立一個索引
    PUT /test01
    當我們這樣建立一個索引的時候,索引採用的是預設的配置,新的欄位通過動態對映的方面新增到型別對映
  • 現在我們需要對建立這個索引的過程做更多的控制,我們想要這個索引有數量適中的主分片
    並且我們在索引任何資料前,分析器和對映已經被建立好
  • 為了達到這個目的我們需要手動建立索引,在請求體裡面傳入設定和型別對映,
{
    "settings": { ... any settings ... },
    "mappings": {
        "type_one": { ... any mappings ... },
        "type_two": { ... any mappings ... },
        ...
    }
}

注意:我們之後可以使用索引模板來預配置開啟自動建立索引,這在索引日誌資料時尤其有用
你將日誌資料索引在一個以日期結尾的索引上,子夜時分,一個預配置的新索引將會自動建立

刪除一個索引

DELETE /my_index

  1. 也可以這樣刪除多個索引
    DELETE /my_index,myindex2
    DELETE /index_*
  2. 刪除全部索引
    DELETE /*
    DELETE /_all

索引設定

  1. es提供了優化好的預設配置,除非你理解了這些配置的作用並且知道為什麼要去修改,否則不要隨意修改
  • 下面是兩個比較重要的設定
    number_of_shards: 每個索引的主分片數,預設值是1,這個配置在索引建立後不能修改
    number_of_replicas: 每個主分片的副本數,預設值是1,對於活動的索引庫,這個配置可以隨時修改
    例如,我們可已建立一個只有一個主分片,沒有副本的小索引
    PUT /my_index
{
    "settings": {
        "number_of_shards": 1,
        "number_of_replicas": 0
    }
}

然後我們可以利用update-index-settings API動態修改副本數,
PUT /my_index/_settings
將剛剛建立的my_index副本數量從0改為1

{
    "number_of_replicas": 1
}

配置分析器

  1. 第三個重要的索引設定是analysis, 用來配置已存在的分析器或者針對你的索引建立新的自定義分析器
    前面介紹了一些內建分析器,用來將全文字串轉換為適合搜尋的倒排索引
  • standard分析器適用於全文欄位的預設分析器,對於大部分西方語系來說不錯
  • standard分詞器,通過單詞邊界分割輸入的文字
  • standard語彙單元過濾器,整理分詞器觸發的語彙單元
  • lowercase語彙單元過濾器,轉換所有的語彙單元為小寫
  • stop語彙單元過濾器,刪除停用詞和對搜尋相關性影響不大的常用詞,如a the and is
  1. 預設情況下,停用詞過濾器是被禁用的
    如果需要啟動它,你可以通過建立一個基於standard分析器的自定義分析器並設定stopwords引數
    可以給分析器提供一個停用詞列表,或者告知使用一個基於特定語義的停用詞列表
    下面我們建立一個新的分析器,鍵es_std,並使用預定義的西班牙停用詞列表
{
    "settings": {
        "analysis": {
            "analyzer": {
                "es_std": {
                    "type": "standard",
                    "stopwords": "_spanish_"
                }
            }
        }
    }
}

es_std分析器不是全域性的,它僅僅存在於我們定義的spanish_docs索引中,
為了使用analyze API對它進行測試,我們必須使用特定的索引名spanish_docs
GET /spanish_docs/_analyze

{
    "analyzer": "es_std",
    "text": "El veloz zorro marrón"
}

簡化的結果已經顯示西班牙語停用詞El已被正確的移除

自定義分析器

  1. 雖然es帶有一些現成的分析器,但是es的強大之處在於你可以自己組合字串過濾器、分詞器、詞彙單元過濾器
    來建立自定義的分析器
  2. 一個分析器包含三部分
  • 字串過濾器
    字串過濾器用來整理一個尚未被分詞的字串,例如我們的文字是Html格式的,標籤div或者p等需要清除掉
    此時我們可以使用html清除 字元過濾器來移除所有的html標籤
    一個分析器可以包含0個或多個字元過濾器
  • 分詞器
    一個分析器必須有且僅有一個分詞器,分詞器把字串分解成單個詞條或者詞彙單元,標準分析器裡面的標準分詞器
    把一個字串按照單詞邊界分解成單個詞條,並且移除大部分的標點符號,當然也有其它不同行為的分詞器存在
    例如關鍵詞分詞器完整的輸出接收到的同樣的字串,空格分詞器只根據空格拆分為本,
    正則分詞器根據正則表示式來分割文字
  • 詞彙單元過濾器
    經過分詞後,詞單元流會按照順序經過詞彙單元過濾器,詞單元過濾器可以新增、修改、刪除詞單元
    向lowercase和stop詞過濾器,但是es裡面還有很多詞單元過濾器,詞幹過濾器把詞單元遏制為詞幹
  1. 建立一個自定義分析器
    和我們之前配置es_std分析器一樣,我們可以在analysis下配置字串過濾器、分詞器、詞彙單元過濾器
    我們來建立一個自定義分析器:
  • 使用html清除 字元過濾器來移除html部分
  • 使用一個自定義的對映 字元過濾器來吧&替換為and
  • 使用標準分詞器分詞
  • 小寫詞條,使用小寫詞過濾器處理
  • 使用自定義停止詞過濾器移除自定義的停止詞列表中包含的詞,
{
    "settings": {
        "analysis": {
            "char_filter": {
                "&_to_and": {
                    "type": "mapping",
                    "mappings": [
                        "&=> and "
                    ]
                }
            },
            "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"
                    ]
                }
            }
        }
    }
}

索引被建立以後,使用analyze API來測試這個新的分析器
GET /my_index/_analyze

{
    "analyzer": "my_analyzer",
    "text": "a the & ABD <p>12345</p>"
}

分析結果:

{
    "tokens": [
        {
            "token": "and",
            "start_offset": 6,
            "end_offset": 7,
            "type": "<ALPHANUM>",
            "position": 2
        },
        {
            "token": "abd",
            "start_offset": 8,
            "end_offset": 11,
            "type": "<ALPHANUM>",
            "position": 3
        },
        {
            "token": "12345",
            "start_offset": 15,
            "end_offset": 20,
            "type": "<NUM>",
            "position": 4
        }
    ]
}

可以看到效果,詞單元過濾器中的my_stopwords去掉了a和the詞條,字元過濾器中的&_to_and將&替換成了and
內建詞彙過濾器lowercase將ABC轉換成了abd,內建字元過濾器html_strip將html標籤直接去掉了

  • 注意,這個分析器目前是沒有多大用處的,除非我們告訴es在哪裡用上它,
  • 我們可以像下面這樣把該分析器用在text欄位上
    PUT /my_index/_mapping
{
    "properties": {
        "title": {
            "type": "text",
            "analyzer": "my_analyzer",
            "fields": {
                "keyword": {
                    "type": "keyword",
                    "ignore_above": 256
                }
            }
        }
    }
}

然後我們使用analyze API介面測試一下我們新建的分析器如何
GET /my_index/_analyze/

{
    "field": "title",
    "text": "中國我愛你, & <p>the</p> aBB"
}

返回結果

{
    "tokens": [
        {
            "token": "中國",
            "start_offset": 0,
            "end_offset": 2,
            "type": "CN_WORD",
            "position": 0
        },
        {
            "token": "我愛你",
            "start_offset": 2,
            "end_offset": 5,
            "type": "CN_WORD",
            "position": 1
        },
        {
            "token": "愛你",
            "start_offset": 3,
            "end_offset": 5,
            "type": "CN_WORD",
            "position": 2
        },
        {
            "token": "abb",
            "start_offset": 20,
            "end_offset": 23,
            "type": "ENGLISH",
            "position": 3
        }
    ]
}

自定義分析器很強大啊!

對映

  1. 對映就像資料庫中的schema,描述了文件可能具有的欄位或者屬性,每個欄位的資料型別比如integer date bool text等
    以及lucene是如何索引和儲存這些欄位的
  2. lucene如何處理文件
    lucene中一個文件有簡單的鍵值對組成,當我們在Lucene中索引一個文件時,每個欄位的值都被新增到相關欄位的倒排索引中去
    lucene也沒有對映的概念,對映是es將複雜的json文件對映成lucene需要的扁平化資料的方式
{
  "name": {
    "type": "text",
    "analyzer": "whitespace"
  }
}

name欄位的對映可以宣告該欄位是text型別,並且它的值被索引到name欄位的倒排索引之前
需要通過whitespace分詞器分析

根物件

對映的最高一層被稱為根物件,他可能包含下面幾項

  1. 一個properties節點列出了文件中可能包含的每個欄位的對映
  2. 各種元資料欄位例如:_id,_source
  3. 屬性:
    type:欄位的資料型別例如:text、date
    analyzer: 確定在索引和搜尋時,全文欄位使用的analyzer
    index: 布林型別,索引還是不索引(注意:如果是字串需要跟欄位型別keyword配合使用)
{
    "properties": {
        "name": {
            "type": "keyword",
            "index": false
        }
    }
}
  1. 元資料_source欄位
    在一個搜尋請求體裡,如果我們只想要_source中的指定欄位,可以這樣查詢
    GET /us/_search
{
    "query": {
        "match": {
            "tweet": "API"
        }
    },
    "_source": ["date", "tweet"]
}

這些欄位值會從_source欄位提取和返回,而不是返回整個_source
注意:在es中對個別欄位設定儲存的方法總不是最優的,整個文件已經被儲存為_source欄位,
使用_source欄位提取你想要的欄位才是最好的

動態對映

  1. 當es遇到文件中以前未遇到的欄位時,他用dynamic mapping來確定欄位的資料型別,
    並自動把新的欄位新增到型別對映中去

索引別名和零停機

  1. 前面提到的重建索引的問題就是必須更新應用中的索引名稱,索引別名就是用來解決這個問題的
    索引別名就像一個快捷方式或者軟連線,可以指向一個或者多個索引,也可以給任何一個需要索引名的API來使用
  • 在執行的叢集中可以無縫從一個索引切換到另一個索引
  • 給多個索引分組
  • 給索引的一個子集建立檢視
  1. 看一下在零停機下從舊索引切換到新索引
    有兩種方式管理別名:_alias用於管理單個操作,_aliases用於執行多個原子操作
    我們假設你有一個應用名叫my_index的索引,事實上my_index是指向真實索引的別名
    真實索引包含一個版本號my_index_v1,my_index_v2
  2. 首先建立索引my_index_v1,然後將別名my_index指向它
PUT /my_index_v1 
PUT /my_index_v1/_alias/my_index 

建立索引my_index_v1,然後將索引別名my_index指向my_index_v1
可以檢測這個別名指向哪一個索引
GET //_alias/my_index
或者哪些別名指向這一個索引
GET /my_index_v1/_alias/

兩者都會返回同樣的結果

{
    "my_index_v1": {
        "aliases": {
            "my_index": {}
        }
    }
}

然後我們決定修改索引中一個欄位的對映,當然我們不能修改現存的對映,所以我們必須重新索引資料
首先我們用新對映建立索引my_index_v2
/my_index_v2

{
    "mappings": {
        "properties": {
            "tags": {
                "type": "keyword",
                "index": false
            }
        }
    }
}

然後我們將資料從my_index_v1遷移到my_index_v2,一旦我們確定文件已經被正確的重新索引了,
我們就將別名指向新的索引,一個別名可以指向多個索引,所以我們在新增別名到新的索引時必須從舊的索引中移除掉
這個操作需要原子化,這意味著我們需要使用_aliases操作
POST /_aliases

{
    "actions": [
        {
            "remove": {"index": "my_index_v1", "alias": "my_index"}
        },
        {
            "add": {"index": "my_index_v2", "alias": "my_index"}
        }
    ]
}

你的應用已經在零停機的情況下從舊索引遷移到了新索引了,即使你認為現在的索引已經設計的很完美了,
在生產環境中還是有可能需要做一些修改的

  • 做好準備:在你的應用中使用別名而不是索引名,然後你就可以在任何時候重建索引
  • 別名的開銷很小,應該廣泛使用

參考文件