ElasticSearch 6.4.2 をさわってみた
データを全文検索するためのエンジンであるElasticSearch
を触っていきたいと思います。全文検索というと WEB ページや文書のキーワード検索として広く利用されていますが、最近では RDB への参照性能を改善するため、代替手段として使われる場面も多いようです。RDB から適切なタイミングでデータを同期してやる必要があるものの、複数のテーブルやデータベースから必要なデータのみを集約して参照させるという用途では、RDB よりもはるかに高速にアクセスでき、RDB とは切り離した擬似的な参照系として構築できる点が評価されているようです。ElasticSearch
も他の分散システムと同じくノードを複数台用意したクラスター構成をとることができますが、今回は手始めということで、シングルノード構成での環境構築からやってみたいと思います。ElasticSearch をインストールする
公式サイトのダウンロードページからElasticSearch
の最新版をダウンロードします。現時点での最新版は 6.4.2
でした。Linux 向けには rpm パッケージが公開されていたので、これを使うことにします。ダウンロードした
rpm
パッケージをインストールします。# rpm -ivh elasticsearch-6.4.2.rpm
ElasticSearch
をインストールすると、/etc/elasticsearch/elasticsearch.yml
として設定ファイルが作られます。シングルノード構成の場合には特に elasticsearch.yml
を編集しなくても動くのですが、複数ノード構成でクラスターを組む場合には書き変えてやる必要があります。インストールした
ElasticSearch
は、systemctl start
コマンドから起動できます。# systemctl start elasticsearch.serviceまた、自動起動を有効化する場合は
systemctl enable
しておきましょう。# systemctl enable elasticsearch.service
起動後には起動確認をしましょう。
ElasticSearch
はすべて 9200
ポートから WEB API にて操作できるようになっていて、http://localhost:9200
にアクセスするとバージョン情報等を確認することができます。$ curl http://localhost:9200 { "name" : "EDfpuKk", "cluster_name" : "elasticsearch", "cluster_uuid" : "OJ4bRWE7QYaEGTRXuSAuaQ", "version" : { "number" : "6.4.2", "build_flavor" : "default", "build_type" : "rpm", "build_hash" : "04711c2", "build_date" : "2018-09-26T13:34:09.098244Z", "build_snapshot" : false, "lucene_version" : "7.4.0", "minimum_wire_compatibility_version" : "5.6.0", "minimum_index_compatibility_version" : "5.0.0" }, "tagline" : "You Know, for Search" }ひとまず JSON 形式で応答が返ってきていれば問題なく動いています。バージョン番号も
6.4.2
になっています。ElasticSearch でのデータ構造
構築したElasticSearch
を使ってみる前に、データ構造にまつわる用語について先に触れておこうと思います。ドキュメント
ElasticSearch
によって検索する文書の 1 つ 1 つをドキュメントと呼びます。ドキュメントは、キーと値のペアによるフィールドを任意の数持つことができます。フィールドの値は、文字列型(text
, keyword
等)、数値型(integer
, long
, float
等)、真偽値型(boolean
)等のデータ型を設定することができます。データ型にはこの他にも、任意のデータ型の要素を任意の数もてる配列型や、他のドキュメントを入れ子として持つことができるオブジェクト型などがあります。ドキュメントがどのようなフィールドで構成されているかをドキュメントタイプと呼びます。RDB においてドキュメントを各レコードとすると、ドキュメントタイプはテーブルに近いです。
また、ドキュメントタイプを具体的に記述したものをマッピングと呼びます。
ElasticSearch
では基本的にあらゆるものを JSON 形式で記述するので、ドキュメントタイプも JSON 形式で書いたマッピングによって表現されます。例えば、以下のマッピングは、タイトル名と著者名というフィールドによって構成されるドキュメントタイプのマッピングになります。
{ "properties": { "title": { "type": "text" }, "author": { "type": "text" } } }
properties
内に、各フィールドの名前とデータ型を定義していきます。この例では title
も author
も text
型としました。また、このドキュメントタイプに実際に入れられるドキュメントは、以下のように記述されます。
{ "title": "枕草子", "author": "清少納言" }
インデックス
ElasticSearch
におけるドキュメントの集合をインデックスと呼びます。ドキュメントの検索はこのインデックスに対して行われるため、意味のあるひとまとまりのドキュメントの集合として、インデックスを設計するとよいです。もちろん厳密には複数のインデックスに対して検索をすることもできるのですが、ElasticSearch
内でのデータはインデックスとしてまとめられて配置されるので、設計もインデックスを基本として考えていくといいと思います。インデックスとドキュメントタイプの違いが最初はわかりづらいかもしれません。厳密な用語の定義としては、ドキュメントを含むドキュメントの集合そのものをインデックスと呼び、ドキュメントの構造をドキュメントタイプと呼びますが、感覚としては近く感じられると思います。
最近の
ElasticSearch
ではインデックス内に定義できるドキュメントタイプは 1 つだけ(となるよう移行している)のですが、古いバージョンの ElasticSearch
では、1 つのインデックスに複数のドキュメントタイプを持たせることができました。インデックス配下に N 個のドキュメントタイプが存在しうることがあったため、現在よりもインデックスとドキュメントタイプの違いはイメージしやすい状況でした。なお、インデックス配下のデータ単位としてのドキュメントタイプが廃止されるまでの流れについては、こちらに詳しく記載されています。
ElasticSearch を使ってみる
それでは最後に ElasticSearch を使っていきたいと思います。まずはインデックスを作り、そこにマッピングを作り、ドキュメントを入れて準備をしてみます。ElasticSearch
への作業はすべて HTTP
から行っていきます。インデックスとマッピングを作る
インデックスの作成とドキュメントタイプの作成は同時に行うことができます。以下は
books
というインデックスと、その中の _doc
というドキュメントを curl
コマンドから同時に作成している例です。アクセスする URL 内にはインデックス名を入れ、HTTP リクエストボディとして送信する JSON の mappings 内のルート要素としてドキュメントタイプ名を記述します。ドキュメントタイプには名前として
_doc
を指定していますが、前述の通り 1 インデックス 1 ドキュメントタイプ化の流れがあるため、固定値として _doc
を使うものと考えたほうがよいです。$ curl -XPUT http://localhost:9200/books -H "Content-type: application/json" -d '{ "settings": { "number_of_replicas": 1, "number_of_shards": 1, "analysis": {}, "refresh_interval": "1s" }, "mappings": { "_doc": { "properties": { "title": { "type": "text" }, "author": { "type": "text" } } } } }'API 呼び出しが成功すれば、
acknowledged
値が true となっている JSON レスポンスが返ってきます。送信しているマッピングには、
settings
要素としていくつかの設定値を記載していますが、最初はこの辺は気にしなくてよいと思います。ElasticSearch
でクラスターを組むようになると number_of_replicas
や number_of_shards
を使う場面が出てくるようになります。ドキュメントを作成する
次に、作ったインデックスにドキュメントを追加していきます。ドキュメントは/{インデックス名}/_doc
に対して JSON 形式でデータを POST すると作ることができます。$ curl -XPOST http://localhost:9200/books/_doc -H "Content-type: application/json" -d '{ "title": "枕草子", "author": "清少納言" }'また、複数のドキュメントを一度に作りたい場合には、
/_bulk
エンドポイントに対して JSON データを POST します。この時、各データは 1 行で記述すること、各データの前にはインデックス名、ドキュメント名(
_doc
)を記述することに注意してください。$ curl -XPOST http://localhost:9200/_bulk -H "Content-type: application/json" -d ' { "index": { "_index": "books", "_type": "_doc" } } { "title": "方丈記", "author": "鴨長明" } { "index": { "_index": "books", "_type": "_doc" } } { "title": "徒然草", "author": "吉田兼好" } '
ドキュメントを読んでみる
作成したドキュメントをインデックスから読み込むには、/{インデックス名}/_doc/_search
に対して GET リクエストを送ります。さらにリクエストパラメーターとして pretty
をつけておくと、レスポンスの JSON が整形されて出力されるので便利です。$ curl -XGET http://localhost:9200/books/_doc/_search?pretty { "took": 1, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": 3, "max_score": 1, "hits": [ { "_index": "books", "_type": "_doc", "_id": "ozVoWGYBQSZoILGk0t8E", "_score": 1, "_source": { "title": "枕草子", "author": "清少納言" } }, { "_index": "books", "_type": "_doc", "_id": "pDVoWGYBQSZoILGk5N-x", "_score": 1, "_source": { "title": "方丈記", "author": "鴨長明" } }, { "_index": "books", "_type": "_doc", "_id": "pTVoWGYBQSZoILGk5N-x", "_score": 1, "_source": { "title": "徒然草", "author": "吉田兼好" } } ] } }
さきほど作成した 3 件のドキュメントを読むことができました。
ドキュメントは作成時に ID を指定しなかった場合、
ElasitcSearch
によって自動で id
値が設定されます。この id
値を指定することで、参照時に特定のドキュメントだけを読むこともできます。$ curl -XGET http://localhost:9200/books/_doc/ozVoWGYBQSZoILGk0t8E?pretty { "_index" : "books", "_type" : "_doc", "_id" : "ozVoWGYBQSZoILGk0t8E", "_version" : 1, "found" : true, "_source" : { "title" : "枕草子", "author" : "清少納言" } }こんな感じですね。
ひとまず今回は環境構築後に触ってみるということで、単純なドキュメントの一覧表示と ID 指定での個別表示までとしておきたいと思います。
ElasticSearch コメント (0) 2018/10/09 20:05:50