RSS2.0

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


公開範囲:
プロフィール HN: ももかん
ゲーム作ったり雑談書いたり・・・していた時期が私にもありました。
カレンダー
<<2018, 10>>
30123456
78910111213
14151617181920
21222324252627
28293031123