Elasticsearch:Index alias


現在讓我們來談談Elasticsearch最簡單和最有用的功能之一:別名 (alias)。為了區分這里alias和文章“Elasticsearch : alias數據類型”,這里的別名(alias)指的是index的別名。 別名正是他們聽起來的樣子; 它們是您可以使用的指針或名稱,對應於一個或多個具體索引。 事實證明這非常有用,因為它在擴展集群和管理數據在索引中的布局方式時提供了靈活性。 即使使用Elasticsearch 只有一個索引的集群,使用別名。 您將在以后感謝我們給予您的靈活性。

別名到底是什么?

您可能想知道別名究竟是什么,以及Elasticsearch在創建別名時涉及何種開銷。 別名將其生命置於群集狀態內,由主節點(master node)管理; 這意味着如果你有一個名為idaho的別名指向一個名為potato的索引,那么開銷就是群集狀態映射中的一個額外鍵,它將名稱idaho映射到具體的索引字符串。 這意味着與其他指數相比,別名的重量要輕得多; 可以維護數千個而不會對集群產生負面影響。 也就是說,我們會警告不要創建數十萬或數百萬個別名,因為在這一點上,即使映射中單個條目的最小開銷也會導致集群狀態增長到大小。 這意味着創建新群集狀態的操作將花費更長時間,因為每次更改時都會將整個群集狀態發送到每個節點。

為什么別名是有用的?

我們建議每個人都為他們的Elasticsearch索引使用別名,因為在重新索引時,它將在未來提供更大的靈活性。 假設您首先創建一個包含單個主分片的索引,然后再決定是否需要更多索引容量。 如果您使用原始別名index,您現在可以將該別名更改為指向另外創建的索引,而無需更改您正在搜索的索引的名稱(假設您從頭開始使用別名進行搜索)。 另一個有用的功能是可以創建不同索引的窗口; 例如,如果您為數據創建每日索引,則可能需要創建一個名為last-7-days的別名的上周數據的滑動窗口; 然后每天創建新的每日索引時,可以將其添加到別名中,同時刪除8天的索引。

另外的一種場景是,當我們修改了我們的index的mapping,讓后通過reindex API來把我們的現有的index轉移到新的index上,那么如果在我們的應用中,我們利用alias就可以很方便地做這間事。在我們成功轉移到新的index之后,我們只需要重新定義我們的alias指向新的index,而在我們的客戶端代碼中,我們一直使用alias來訪問我們的index,這樣我們的代碼不需要任何的改動。

建立index

為了驗證我們的API,我們先建立一些數據:

    PUT twitter/_doc/1
    {
      "user" : "雙榆樹-張三",
      "message" : "今兒天氣不錯啊,出去轉轉去",
      "uid" : 2,
      "age" : 20,
      "city" : "北京",
      "province" : "北京",
      "country" : "中國",
      "address" : "中國北京市海淀區",
      "location" : {
        "lat" : "39.970718",
        "lon" : "116.325747"
      }
    }
     
    PUT twitter/_doc/2
    {
      "user" : "東城區-老劉",
      "message" : "出發,下一站雲南!",
      "uid" : 3,
      "age" : 30,
      "city" : "北京",
      "province" : "北京",
      "country" : "中國",
      "address" : "中國北京市東城區台基廠三條3號",
      "location" : {
        "lat" : "39.904313",
        "lon" : "116.412754"
      }
    }
     
    PUT twitter/_doc/3
    {
      "user" : "虹橋-老吳",
      "message" : "好友來了都今天我生日,好友來了,什么 birthday happy 就成!",
      "uid" : 7,
      "age" : 90,
      "city" : "上海",
      "province" : "上海",
      "country" : "中國",
      "address" : "中國上海市閔行區",
      "location" : {
        "lat" : "31.175927",
        "lon" : "121.383328"
      }
    }

這樣,我們建立了三個文檔的twitter索引。

管理別名

添加一個index alias

一個index別名就是一個用來引用一個或多個已經存在的索引的另外一個名字,我們可以用如下的方法來創建

PUT /twitter/_alias/alias1

請求的格式:

PUT /<index>/_alias/<alias>
POST /<index>/_alias/<alias>
PUT /<index>/_aliases/<alias>
POST /<index>/_aliases/<alias>

路徑參數:

<index>:要添加到別名的索引名稱的逗號分隔列表或通配符表達式。
         要將群集中的所有索引添加到別名,請使用_all值。
<alias>:(必需,字符串)要創建或更新的索引別名的名稱。

比如經過上面的REST 請求,我們為twitter創建了另外一個別名alias1。我們以后可以通過alias1來訪問這個index:

GET alias1/_search

顯示的結果:

    {
      "took" : 0,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 3,
          "relation" : "eq"
        },
        "max_score" : 1.0,
        "hits" : [
          {
            "_index" : "twitter",
            "_type" : "_doc",
            "_id" : "4",
            "_score" : 1.0,
            "_source" : {
              "user" : "朝陽區-老賈",
              "message" : "123,gogogo",
              "uid" : 5,
              "age" : 35,
              "city" : "北京",
              "province" : "北京",
              "country" : "中國",
              "address" : "中國北京市朝陽區建國門",
              "location" : {
                "lat" : "39.718256",
                "lon" : "116.367910"
              }
            }
          },
          {
            "_index" : "twitter",
            "_type" : "_doc",
            "_id" : "5",
            "_score" : 1.0,
            "_source" : {
              "user" : "朝陽區-老王",
              "message" : "Happy BirthDay My Friend!",
              "uid" : 6,
              "age" : 50,
              "city" : "北京",
              "province" : "北京",
              "country" : "中國",
              "address" : "中國北京市朝陽區國貿",
              "location" : {
                "lat" : "39.918256",
                "lon" : "116.467910"
              }
            }
          },
          {
            "_index" : "twitter",
            "_type" : "_doc",
            "_id" : "6",
            "_score" : 1.0,
            "_source" : {
              "user" : "虹橋-老吳",
              "message" : "好友來了都今天我生日,好友來了,什么 birthday happy 就成!",
              "uid" : 7,
              "age" : 90,
              "city" : "上海",
              "province" : "上海",
              "country" : "中國",
              "address" : "中國上海市閔行區",
              "location" : {
                "lat" : "31.175927",
                "lon" : "121.383328"
              }
            }
          },
      ...

顯然這樣做的好處是非常明顯的,我們可以把我們想要的進行搜索的index取一個和我們搜索方法里一樣的別名就可以了,這樣我們可以不修改我們的搜索方法,就可以分別對不同的index進行搜索。比如我們可以用同樣的搜索方法對每天的log進行分析。只有把每天的log的index的名字都改成一樣的alias就可以了。

創建一個基於城市的alias:

    PUT twitter/_alias/city_beijing
    {
      "filter": {
        "term": {
          "city": "北京"
        }
      }
    }

在這里,我們創建了一個名稱為city_beijing的alias。如果我們運行如下的搜索:

GET city_beijing/_search

它將返回所有關於城市為北京的搜索結果:

    {
      "took" : 1,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 4,
          "relation" : "eq"
        },
        "max_score" : 1.0,
        "hits" : [
          {
            "_index" : "twitter",
            "_type" : "_doc",
            "_id" : "4",
            "_score" : 1.0,
            "_source" : {
              "user" : "朝陽區-老賈",
              "message" : "123,gogogo",
              "uid" : 5,
              "age" : 35,
              "city" : "北京",
              "province" : "北京",
              "country" : "中國",
              "address" : "中國北京市朝陽區建國門",
              "location" : {
                "lat" : "39.718256",
                "lon" : "116.367910"
              }
            }
          },
          {
            "_index" : "twitter",
            "_type" : "_doc",
            "_id" : "5",
            "_score" : 1.0,
            "_source" : {
              "user" : "朝陽區-老王",
              "message" : "Happy BirthDay My Friend!",
              "uid" : 6,
              "age" : 50,
              "city" : "北京",
              "province" : "北京",
              "country" : "中國",
              "address" : "中國北京市朝陽區國貿",
              "location" : {
                "lat" : "39.918256",
                "lon" : "116.467910"
              }
    ...

alias也可以在創建index時被創建,比如:

    DELETE twitter
     
    PUT twitter
    {
         "mappings" : {
          "properties" : {
            "address" : {
              "type" : "text",
              "fields" : {
                "keyword" : {
                  "type" : "keyword",
                  "ignore_above" : 256
                }
              }
            },
            "age" : {
              "type" : "long"
            },
            "city" : {
              "type" : "keyword",
              "copy_to" : [
                "region"
              ]
            },
            "country" : {
              "type" : "keyword",
              "copy_to" : [
                "region"
              ]
            },
            "explain" : {
              "type" : "boolean"
            },
            "location" : {
              "type" : "geo_point"
            },
            "message" : {
              "type" : "text",
              "fields" : {
                "keyword" : {
                  "type" : "keyword",
                  "ignore_above" : 256
                }
              }
            },
            "province" : {
              "type" : "keyword",
              "copy_to" : [
                "region"
              ]
            },
            "region" : {
              "type" : "text"
            },
            "uid" : {
              "type" : "long"
            },
            "user" : {
              "type" : "text",
              "fields" : {
                "keyword" : {
                  "type" : "keyword",
                  "ignore_above" : 256
                }
              }
            }
          }
        },
        "aliases": {
          "city_beijing": {
            "filter": {
              "term": {
                "city": "北京"
              }
            }
          }
        }
    }

在這里,我們刪除了twitter索引,同時我們重新定義twitter索引的mapping,並同時定義了city_beijing你別名。重新index我們上面的三個文檔,那么我們再次搜索我們的數據:

GET city_beijing/_search

我們可以看到兩個城市為北京的搜索結果:

    {
      "took" : 0,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 2,
          "relation" : "eq"
        },
        "max_score" : 1.0,
        "hits" : [
          {
            "_index" : "twitter",
            "_type" : "_doc",
            "_id" : "1",
            "_score" : 1.0,
            "_source" : {
              "user" : "雙榆樹-張三",
              "message" : "今兒天氣不錯啊,出去轉轉去",
              "uid" : 2,
              "age" : 20,
              "city" : "北京",
              "province" : "北京",
              "country" : "中國",
              "address" : "中國北京市海淀區",
              "location" : {
                "lat" : "39.970718",
                "lon" : "116.325747"
              }
            }
          },
          {
            "_index" : "twitter",
            "_type" : "_doc",
            "_id" : "2",
            "_score" : 1.0,
            "_source" : {
              "user" : "東城區-老劉",
              "message" : "出發,下一站雲南!",
              "uid" : 3,
              "age" : 30,
              "city" : "北京",
              "province" : "北京",
              "country" : "中國",
              "address" : "中國北京市東城區台基廠三條3號",
              "location" : {
                "lat" : "39.904313",
                "lon" : "116.412754"
              }
            }
          }
        ]
      }
    }

獲取alias

我們可以通過如下的API來獲取當前以及定義好的alias:

GET /_alias
GET /_alias/<alias>
GET /<index>/_alias/<alias>

比如:

GET /twitter/_alias/alias1

這里獲取在twitter下的名字叫做alias1的別名。針對我們的情況,我們使用如下的接口:

GET /twitter/_alias/city_beijing

我們獲取我們之前得到的city_beijing的alias。顯示的結果如下:

    {
      "twitter" : {
        "aliases" : {
          "city_beijing" : {
            "filter" : {
              "term" : {
                "city" : "北京"
              }
            }
          }
        }
      }
    }

你也可以通過如下的wild card方式來獲取所有的alias:

GET /twitter/_alias/*

比如,我們新增加一個alias1的別名:

PUT /twitter/_alias/alias1

上面的wild card方式返回來得結果為:

    {
      "twitter" : {
        "aliases" : {
          "alias1" : { },
          "city_beijing" : {
            "filter" : {
              "term" : {
                "city" : "北京"
              }
            }
          }
        }
      }
    }

顯然這里有兩個別名:alias1及city_beijing。

你可以通過如下的方式來搜尋你的alias:

GET /_alias/city_*

它將顯示名字以city開始的所有的alias。

檢查一個alias是否存在

我們可以通過如下的方式來檢查一個alias是否存在:

HEAD /_alias/<alias>
HEAD /<index>/_alias/<alias>

比如:

HEAD /_alias/alias1

它顯示的結果是:

200 - OK

同樣你也可通過wild card方式來查詢:

HEAD /_alias/city*

這個用來檢查所有以city為開頭的alias。

更新alias

我們這里所說的更新包括:添加及刪除

接口為:

POST /_aliases

比如:

    POST /_aliases
    {
        "actions" : [
            { "add" : { "index" : "twitter", "alias" : "alias2" } }
        ]
    }

在這里,我們為twitter索引添加了一個叫做alias2的別名。運行后,我們可以通過alias2來重新搜索我們的twitter

GET /alias2/_search

我們可以看到我們想要的結果:

    {
      "took" : 0,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 3,
          "relation" : "eq"
        },
        "max_score" : 1.0,
        "hits" : [
          {
            "_index" : "twitter",
            "_type" : "_doc",
            "_id" : "1",
            "_score" : 1.0,
            "_source" : {
              "user" : "雙榆樹-張三",
              "message" : "今兒天氣不錯啊,出去轉轉去",
              "uid" : 2,
              "age" : 20,
              "city" : "北京",
              "province" : "北京",
              "country" : "中國",
              "address" : "中國北京市海淀區",
              "location" : {
                "lat" : "39.970718",
                "lon" : "116.325747"
              }
            }
          },
     
    ...

在action里,我們可以有如下的幾種:

add: 添加一個別名
remove: 刪除一個別名
remove_index: 刪除一個index或它的別名

比如我們可以通過如下的方法來刪除一個alias

    POST /_aliases
    {
        "actions" : [
            { "remove": { "index" : "twitter", "alias" : "alias2" } }
        ]
    }

一旦刪除后,之前的定義的alias2就不可以用了。

重新命名一個alias

重命名別名是一個簡單的刪除然后在同一API中添加操作。 此操作是原子操作,無需擔心別名未指向索引的短時間段:

    POST /_aliases
    {
        "actions" : [
            { "remove" : { "index" : "twitter", "alias" : "alias1" } },
            { "add" : { "index" : "twitter", "alias" : "alias2" } }
        ]
    }

上面的操作,刪除alias1,同時創建一個新的叫做alias2的別名。

我們也可以把同一個alias在指向不同時期的index,比如我們的log index滾動下一個月,我們可以修改我們的alias總是指向最新的index。

為多個索引添加同樣一個alias

將別名與多個索引相關聯只需幾個添加操作:

    POST /_aliases
    {
        "actions" : [
            { "add" : { "index" : "test1", "alias" : "alias1" } },
            { "add" : { "index" : "test2", "alias" : "alias1" } }
        ]
    }

你也可以通過如下的方式,通過一個add命令來完成:

    POST /_aliases
    {
        "actions" : [
            { "add" : { "indices" : ["test1", "test2"], "alias" : "alias1" } }
        ]
    }

甚至:

    POST /_aliases
    {
        "actions" : [
            { "add" : { "index" : "test*", "alias" : "all_test_indices" } }
        ]
    }

這樣所有以test*為開頭的索引都共同一個別名。

當我們index我們的文檔時,對一個指向多個index的別名進行索引是錯誤的。

也可以在一個操作中使用別名交換索引:

    PUT test     
    PUT test_2   
    POST /_aliases
    {
        "actions" : [
            { "add":  { "index": "test_2", "alias": "test" } },
            { "remove_index": { "index": "test" } }  
        ]
    }

在上面的例子中,假如我們地添加了一個叫做test的index,而test_2是我們想要的。我們直接可以通過上面的方法吧test中的數據交換到test_2中,並同時把test索引刪除。

Filtered alias

帶有過濾器的別名提供了一種創建同一索引的不同“視圖”的簡便方法。 可以使用Query DSL定義過濾器,並使用此別名將其應用於所有“搜索”,“計數”,“按查詢刪除”和“更多此類操作”。

要創建過濾后的別名,首先我們需要確保映射中已存在這些字段:

    PUT /test1
    {
      "mappings": {
        "properties": {
          "user" : {
            "type": "keyword"
          }
        }
      }
    }

現在我們可以利用filter來創建一個alias,是基於user字段

    POST /_aliases
    {
        "actions" : [
            {
                "add" : {
                     "index" : "test1",
                     "alias" : "alias2",
                     "filter" : { "term" : { "user" : "kimchy" } }
                }
            }
        ]
    }

Write index

可以將別名指向的索引關聯為write索引。 指定后,針對指向多個索引的別名的所有索引和更新請求將嘗試解析為write索引的一個索引。 每個別名只能將一個索引分配為一次write索引。 如果未指定write索引且別名引用了多個索引,則不允許寫入。

可以使用別名API和索引創建API將與別名關聯的索引指定為write索引。

    POST /_aliases
    {
        "actions" : [
            {
                "add" : {
                     "index" : "test",
                     "alias" : "alias1",
                     "is_write_index" : true
                }
            },
            {
                "add" : {
                     "index" : "test2",
                     "alias" : "alias1"
                }
            }
        ]
    }

在這里,我們定義了alias1同時指向test及test2兩個索引。其中test中,注明了is_write_index,那么,如下的操作:

    PUT /alias1/_doc/1
    {
        "foo": "bar"
    }

相當於如下的操作:

PUT /test/_doc/1

也就是寫入到test索引中,而不會寫入到test2中。

要交換哪個索引是別名的寫入索引,可以利用別名API進行原子交換。 交換不依賴於操作的順序。

    POST /_aliases
    {
        "actions" : [
            {
                "add" : {
                     "index" : "test",
                     "alias" : "alias1",
                     "is_write_index" : false
                }
            }, {
                "add" : {
                     "index" : "test2",
                     "alias" : "alias1",
                     "is_write_index" : true
                }
            }
        ]
    }

參考:
【1】https://www.elastic.co/guide/en/elasticsearch/reference/7.3/indices-aliases.html
【2】https://www.elastic.co/guide/en/elasticsearch/reference/7.3/indices-get-alias.html
【3】https://www.elastic.co/guide/en/elasticsearch/reference/7.3/indices-add-alias.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM