40
29

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

フューチャーAdvent Calendar 2019

Day 19

Elasticsearchで全文検索サービスを作るときに最初に見るべきだったリンク集

Last updated at Posted at 2019-12-18

結論

Elasticsearchをキャッチアップするときはまずは最新版の公式ドキュメントを読みましょう。

やってしまったこと

  • 業務利用(全文検索サービス作成)でElasticsearchを使う機会があり、Elasticsearchのキャッチアップが必要になった
  • とりあえず「Elasticsearch 入門」でググると、「この記事は1年前に作られました」の文字が気になりつつも良さげな実用サンプル付きの日本語記事が複数ヒット
  • 最低限の構成でクエリ検索できるところまでならスムーズに行けるだろうと思いながら記事の通りに手を動かしてみると、思いの外いろいろなところでハマってしまった
    • Dockerイメージが立ち上がらない、インデックスが作れない、日本語検索のスコアがおかしい(日本語の構文解析ができていない)、etc...

ハマった原因

  • Elasticsearchメジャーバージョン間では仕様が大きく異なる箇所が幾つかある
    • 例えばElasticsearch5系→6系に上がる際はインデックス内複数タイプの使用が不可能になったため、それより前(~2017年8月)に書かれた記事通りに動かすとエラーになるケースがある
    • さらに直近の6系→7系アップデートでは更にタイプ自体が廃止(※7系は受け入れAPIのみ。全体廃止は8系予定とのこと)の方針となったため、インデックス作成時のマッピング定義でタイプフィールドが含まれるものはもれなくエラーとなってしまう
  • 「Elasticsearch 入門」などで上位にヒットする日本語記事の幾つかは前バージョンのものを前提にしていることに加え、Elasticsearch自体も頻繁にメジャーバージョンアップデートを行っておりかつ仕様変更も多い
    • このような背景から、「とりあえず日本語の入門記事から取り掛かろう!」とする人たちはハマりやすいのでは?と思いました(私はハマりました…)

この記事の目的

  • そもそもハマらないようにするにはまず最初に公式ドキュメントを読むべき
    • とはいえ公式ドキュメントは全編英語(少なくともCurrentバージョンは)かつ分量が多く(チャプターだけでも29あり、全セクションだと1,000ほどあります)すべてを読み通してから手を付けるのはかなり大変
    • そこで、自分がハマったあとに改めて参照した公式ドキュメント内ページをピックアップし、「やりたいこととそれが載っているページ(+ハマった経験を基にしたコメント)の一覧」を作ってみました
    • 公式ドキュメントの読み進め方の1つとして、これからキャッチアップする人が少しでも参考になれば幸いです

注意事項

  • この記事自体も2019年12月現在のバージョン7.5に依存して書かれているため、仕様変更等で将来的に遷移先URLがリンク切れになっている場合や、解決しない場合が起こりうるかもしれません

公式ドキュメントの基本の歩き方

Elastic Stack and Product Documentation

  • Elastic社の提供する諸製品(Elasticsearch, Kibana, Beats, Logstash)が網羅されているページ
  • 分量がとてつもなく多いので、とりあえずElasticsearchを使いたい場合は後回しで見たほうがいいかも

Elasticsearch Reference

上記の Elastic Stack and Product Documentation -> Elasticsearch: Store, Search, and Analyze -> Elasticsearch Reference [<カレントバージョン>] よりアクセス可能

  • Elasticsearchで分からないことがあれば、このページから辿って探していくのが基本
    • …が、やはり1からすべて読み通そうとなるとかなりの分量となるため、まずはやりたいことベースで掻い摘んで読めるようになっていくのが良さそう
  • URIは全ページ /guide/en/elasticsearch/reference/<参照バージョン>/xxx.html という構成なっており、参照バージョン箇所をcurrentにするといつでも最新版の情報のページにアクセスできる(はず)です
    • Google検索から参照した場合や外部記事の参考文献から飛んだ場合、旧バージョンのページが表示されることがありうるので注意
    • また各ページの冒頭には所謂パンくずリスト(下図)があり、チャプター・セクション・ページごとの位置関係を把握しておくと効率よくキャッチアップできると思います
    • Install_Elasticsearch_with_Docker___Elasticsearch_Reference__7_5____Elastic.png

やりたいこと別、最初に見ておくと良さそうな公式ドキュメント内ページ一覧

インストール編

docker-compose.ymlを書いて、最低限の構成で立ち上がるようにする

Install Elasticsearch with Docker | Elasticsearch Reference

  • 最小構成の場合は「Starting a single node cluster with Docker」に従う
    • 同ページ中程にいい感じのdocker-compose.ymlがありますが、そちらはmulti-node cluster(複数ノード構成)なのでキャッチアップとしては少し複雑になってしまう
    • 以下のように「Starting a single node cluster with Docker」記載のdocker runコマンドをdocker-compose.yml向けに書き換えるのが良さそう
docker-compose.yml
version: '2'
services:
  elasticesarch:
    build: docker/elasticsearch # 後述のDockerfileを参照
    container_name: elasticsearch
    restart: always
    ports:
      - "9200:9200"
      - "9300:9300"
    environment:
      - "discovery.type=single-node"

ただしドキュメント記載の通り、single node(単体ノード構成)はテストor開発環境のみの使用とすべきです。念の為。

セットアップ編

日本語で検索ができるようにする

Japanese (kuromoji) Analysis Plugin | Elasticsearch Reference

Elasticsearch Plugins and Integrations -> Analysis Plugins -> Japanese (kuromoji) Analysis Plugin より参照可能

  • Elasticsearchはデフォルトで日本語解析プラグインが未インストールのため、日本語解析・および検索をするためには上記ドキュメント記載のインストール手順を別途実行する必要あり
  • Dockerの場合はDockerfileに以下のように書いておくと、立ち上げ時にインストール済み状態になってくれます
    • <タグ名>は前項のInstall Elasticsearch with Dockerからアクセス可能なdocker.elastic.coの一覧から選択
docker/elasticsearch/Dockerfile
FROM docker.elastic.co/elasticsearch/elasticsearch:<タグ名>
RUN elasticsearch-plugin install analysis-kuromoji

日本語解析が可能なインデックスを作る

analyzer | Elasticsearch Reference

  • Elasticsearchは動的マッピング機能があるため、そもそもインデックスを作る際のマッピング定義の指定は必須ではない
  • しかしデフォルトの定義ではAnalyzer(構文解析)が日本語に適していないため、そのまま日本語ドキュメントを投入すると投入時点で日本語文字が1文字ずつ細切れで格納されてしまい正しい検索スコアが出せない
  • とりあえず最低限の日本語解析がやりたい場合は、マッピング定義内のproperties内オブジェクトごとにAnalyzerの指定をすればOK
    • フィルター等を組み合わせることでより高度な構文解析ができたり、properties内オブジェクトごとにAnalyzeの有効/無効を切り替えてパフォーマンスチューニングしたりできますが今回は割愛…
    • 公式ドキュメントにはすぐに使える日本語解析用のいい感じのサンプルがないため、このあたりはElasticsearchのバージョン違いによる仕様変更に注意(↓のJSON内コメント参照)しつつ「elasticsearch kuromoji mapping」等でググりつつ日本語記事を探すのが良いかなと思います
curl -X PUT http://localhost:9200/hoge-index -H 'Content-Type: application/json' -d @mapping.json
mapping.json
{
  "mappings": { // 6系以前は直下の行にtypeフィールドがあったが7系以降は廃止された
    "properties": {
      "article": { 
        "type":     "text", // <- 6系以降は"string"を使うとエラーになる
        "analyzer": "kuromoji" // <- 日本語構文解析用のAnalyzerを指定
      }
    }
  }
}

実行後は、正しく生成できたかどうか確認しておくと良いです。

$ curl localhost:9200/hoge-index?pretty
{
  "hoge-index" : {
    "aliases" : { },
    "mappings" : {
      "properties" : {
        "article" : {
          "type" : "text",
          "analyzer" : "kuromoji"
        }
      }
    },
    "settings" : {
      "index" : {
        "creation_date" : "xxx",
        "number_of_shards" : "1",
        "number_of_replicas" : "1",
        "uuid" : "xxx",
        "version" : {
          "created" : "xxx"
        },
        "provided_name" : "hoge-index"
      }
    }
  }
}

ドキュメントを投入する(バルクインサート)

Bulk API | Elasticsearch Reference

  • PUTで1レコードずつ挿入もできるが、上記内ページ記載の通りバルクインサートのほうがパフォーマンスが良くなるらしい
    • スクリプト書くにしてもBulk API使ったほうが勝手が良いかと
  • バージョン違いによる仕様変更はあまり無いので、実用的なサンプルとして旧バージョンの日本語記事を参照しても大丈夫そう
    • 7系以降で_type指定が廃止された点のみ注意
  • AWSのマネージド型Elasticsearchの場合は、HTTPリクエストペイロードのサイズに制限があるため、大量データのバルクインサート用スクリプトを作る際は分割しながら送るようにする必要があることに注意

検索編

Query DSL | Elasticsearch Reference

  • インストールとセットアップの山さえ乗り越えてしまえば、検索クエリのキャッチアップはそこまで大変ではないと思うのでさっくりとリンクのみ紹介
    • インストールとセットアップはエラーの度にインデックス削除&再生成が必要だが、検索クエリは再度投げるだけなのでトライ&エラーのテンポが速くなる
  • 基本的には上記のQuery DSLの必要そうな記事を読み進めればOK
    • 以下、やりたいこととマッチしそうな記事をピックアップしました

完全一致で検索する(キーワード検索)

Term query | Elasticsearch Reference

日本語の表記揺れも含めて検索する(全文検索)

Match query | Elasticsearch Reference

複数のフィールドや検索条件から検索する

Boolean query | Elasticsearch Reference

OR検索やAND検索を可能にする

Query string query | Elasticsearch Reference
Simple query string query | Elasticsearch Reference

  • OR検索やAND検索のみであればSinmple query string queryでOK
  • 外部公開する場合などはSimple query string queryを使い、かつ機能制限をかけたほうが安全
    • Query string queryは複雑なクエリを簡単に投げられるので、サーバリソース消費の攻撃を受けるリスクが高い

検索結果にスニペットとハイライト表示を含める

Request Body Search#Highlighting | Elasticsearch Reference

  • スニペット?ハイライト?と最初は思っていたので、Google検索画面を例として説明してみると、下図のような検索ヒット対象の文章の一部と単語の箇所のハイライト表示(<highlight>タグで格納される)が取得できるイメージ
    • elasticsearch_-_Google_検索.png
    • 公式ドキュメントのNOTE記載の通り、計算コストが高い機能のため、検索結果の全件に対して適応してしまうと途端にパフォーマンスが悪くなってしまうので注意。ページネーション機能を利用して、全件ではなくページ表示対象の件数分にのみ適応させる工夫が必要

おわりに

とりあえず上記で挙げたあたりの記事を読めば、最低限動くものが作れるようになると思います。
これからのステップアップの目標としては「検索精度を上げたい」「パフォーマンスを向上させたい」などといったことを決めてから

  • まずは現行バージョンの公式ドキュメントを読みながら
  • 必要に応じて日本語検索用の実装サンプルを(記事を書いた人の想定バージョンに注意しながら)ググっていく

スタイルで進めていくのがいいかなと思います。

40
29
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
40
29

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?