Elasticsearch インデックス・エイリアス

Elasticsearch Index Aliases — インデックス・エイリアスの活用あれこれ

Kunihiko Kido
Hello! Elasticsearch.

--

リインデックスってどうやるんだろう?と思い調べていたところ、エイリアスの方が気になってしまったので先にまとめ。

インデックス・エイリアスとは?

インデックス・エイリアスはその名の通りインデックスに別名をつけられる機能のこと、同じエイリアス名を複数のインデックスにつけることもできるし、1つのインデックスに複数のエイリアス名をつけることもできます。FAST ESP のサーチプロファイルっぽい!または、リレーショナルDBのビューみたい!なイメージの機能です。

実際の設定は、各インデックスに対してエイリアス名を設定するのですが、理解するイメージは下の図の方がイメージしやすいかと思います。

インデックス・エイリアス

エイリアスを使わない場合は、直接インデックスを指定して検索するわけですが、クライアントからエイリアス宛に検索するようにすることで、検索対象のインデックスをElasticsearch側でコントロールできるということです。また、エイリアス機能には別名以外にも任意の絞り込み条件であらかじめフィルタリングしておけるフィルター機能と、ドキュメントの物理的な配置 シャード をコントロールする為のルーティング機能が提供されています。

エイリアスの活用その1:任意のタイミングで新しいインデックス情報を追加する

例えば、新しい商品カテゴリを公開したい場合、1つのインデックスで商品情報全てを管理している場合は、インデックスされた商品から徐々に検索結果に反映されるわけですが、商品カテゴリ毎にインデックスを作成する仕様で、エイリアスを使っていれば、新しい商品カテゴリの商品情報を別でインデックスしておいて、任意のタイミングで一気に公開することができます。実際検索エンジンを運用しているとこういう要望多いです。

簡単に手順をまとめてみます。

カテゴリ毎にインデックスを作成:

インデックスを作成し、データをインデックスしてください。

$ curl -XPUT 'localhost:9200/category1'
$ curl -XPUT 'localhost:9200/category2'
...

各インデックスに共通のエリアス名を設定:

“products” と言う名前の共通のエイリアス名を設定しています。

curl -XPOST 'http://localhost:9200/_aliases' -d '
{
"actions" : [
{ "add" : { "index" : "category1", "alias" : "products" } },
{ "add" : { "index" : "category2", "alias" : "products" } }
]
}'

設定したエイリアスを確認:

「*」の代わりに、インデックス名を指定すると、指定したインデックスのみのエイリアス情報が確認できます。

$ curl -XGET 'localhost:9200/*/_alias?pretty=true'
{
"category2" : {
"aliases" : {
"products" : { }
}
},
"category1" : {
"aliases" : {
"products" : { }
}
}
}

クライアントアプリは、インデックス名の代わりにエイリアス名”products”を指定して検索すると、”category1” と”category2” のインデックスを対象に検索することができます。

新しいカテゴリを追加:

まずは、インデックスを作成しデータをインデックスします。

$ curl -XPUT 'localhost:9200/category3'
...

検索対象に新しいカテゴリを含める:

新しく追加したインデックスを検索対象に含めるには、検索共通のエイリアス名を設定します。※ 一つのエイリアス追加する場合は、次のようにも指定できます。

curl -XPUT 'localhost:9200/category3/_alias/products'

エイリアスの活用その2:停止せずに再作成したインデックス仕様に切り替える

本番運用していると、検索仕様やデータ仕様の変更でフィールドの追加やマッピングの変更など発生します。Elasticsearch に関わらずほとんどの検索エンジンは検索・インデックス仕様の変更を伴うものは、インデックスを再作成する必要があります。変更の内容によっては単にリビルドし直せば良いものもありますが、別に再作成する必要のある場合は、クライアントのアプリケーションの修正が必要になってしまいます。エリアスを使うことで、クライアントの修正することなく、停止せずに再作成したインデックスに切り替えることが可能です。

簡単に手順をまとめてみます。

インデックスとエイリアスの作成:

まずは、切り替える前のインデックスと検索に使用するエイリアス名を作成します。

$ curl -XPUT 'localhost:9200/products_v1'
$ curl -XPUT 'localhost:9200/products_v1/_alias/products'

クライアントアプリは、エイリアス名 “products” に対して検索するように実装します。

新しい仕様のインデックスを作成:

次に、マッピング定義などを変更した新しい仕様のインデックスを同じデータを使って作成します。

$ curl -XPUT 'localhost:9200/products_v2'
...

再作成したインデックスに切り替える:

既存のインデックスをエイリアスから削除し、再作成したインデックスをエイリアスに含めます。

curl -XPOST 'http://localhost:9200/_aliases' -d '
{
"actions" : [
{"remove": {"index": "products_v1", "alias": "products" }},
{"add" : {"index": "products_v2", "alias": "products" }}
]
}'

以外と簡単ですね。テスト用のエイリアスも作成しておけば、事前に確認テストもできるので、安心してリリースできそうです。

エイリアスの活用その3:用途別にエイリアスを提供する

例えば、新商品のみを対象にしたクエリ、セール商品のみを対象にしたクエリなど、1つのサイトの中でも同じフィルター条件をいろいろなところで必要とするケースは多いのではないでしょうか?スマホのアプリでもウェブのアプリでも同じサイトであれば新商品と言うフィルター条件はほとんどの場合同じです。アプリケーション毎にこれらのクエリを組み立てている場合、その仕様が変更されれば当然アプリケーションの修正が必要になってしまいます。エイリアスを使うことでこれらを解決するには、1つのインデックスに対して用途別にフィルター条件が設定されたエイリアスを提供することです。ちなみにベースの絞り込み条件がElasticsearch側で吸収できるので、アプリケーション側のクエリの組み立てもシンプルになりますよね?

簡単に手順をまとめてみます。

インデックスの作成:

$ curl -XPUT 'localhost:9200/products'

用途別のエイリアスを作成:

次の例では、1つのインデックスに対して、絞り込み条件が異なる用途別の3つのエイリアスを作成しています。

  • all_products
    全ての商品を対象にしたエイリアス
  • new_products
    新しい商品のみを対象にしたエイリアス
  • sale_products
    セール商品のみを対象にしたエイリアス
$ curl -XPOST 'http://localhost:9200/_aliases' -d '
{
"actions" : [
{
"add" : {
"index": "products",
"alias": "all_products"
},
"add" : {
"index": "products",
"alias": "new_products",
"filter": {"term": {"status": "new"}}
},
"add" : {
"index": "products",
"alias": "sale_products",
"filter": {"term": {"status": "sale"}}
}
}
]
}'

作成したエイリアスを確認:

$ curl -XGET 'localhost:9200/products/_alias?pretty=true'
{
"products" : {
"aliases" : {
"sale_products" : {
"filter" : {
"term" : {
"status" : "sale"
}
}
},
"all_products" : { },
"new_products" : {
"filter" : {
"term" : {
"status" : "new"
}
}
}
}
}
}

あとは、アプリケーションを実装する際にインデックスの代わりに用途別のエイリアスを使って検索クエリを実装するだけです。実際の業務で使用する場合は絞り込み条件仕様はもっと複雑になるケースが多いですので、その条件が Elasticsearch 側で吸収できるのはかなり使い勝手が良いのでは?

ルーティング機能はさておき、シンプルかつ便利なエイリアス機能です。本番リリース後も検索仕様の変更やデータ変更などは必ずと言ってよいほど発生しますので、このエイリアス機能は必須で使っておきたいですね。

今回思いついたのは、とりあえずこの3つです。また何か思いついたら追記します。

--

--