LoginSignup
10
0

More than 5 years have passed since last update.

Elasticsearch利用まとめ2018

Last updated at Posted at 2018-12-09

はじめに

classiでは全文検索でElasticsearchを使用しています。今年を振り返って改めてclassiでの使われ方を紹介したいと思います。
ちなみに実装言語としてruby、フレームワークとしてRailsを使っています。mappingの定義やindexの定義の仕方はelasticsearch-rails(elasticsearch-model)での書き方で書いてます。ご了承ください。 :bow:

どのような使い方をしているか

classiでは主に以下の機能でElasticsearchを使っています。

  • テスト、問題、アンケート、自分であげた画像に対するキーワード検索
  • 先生・生徒のコミニケーション機能の各メッセージに対してのキーワード検索
  • 動画コンテンツのキーワード検索

では順にどのような使い方をしているかを説明します。

テスト、問題、アンケート、自分であげた画像に対するキーワード検索

ここでは検索対象のデータをjson形式にしてElasticsearchに登録しています(普通の使い方ですね)。versionもまだ2系( :bow: )なので、mappingも以下のような形(例)で定義しています。

indexes :id,  type: 'long', index: 'not_analyzed' 
indexes :name,  type: 'string', analyzer: 'kuromoji_analyzer', fields: { raw: { type: 'string', index: :not_analyzed } } 
indexes :owner_id, type: 'long'
indexes :sentence, type: 'string', analyzer: 'kuromoji_analyzer' 

versionが5系であれば、type: 'string'でなくtype: 'text'になりますが、まだversion2系のままなので、stringになっています。
また検索クエリーではキーワード検索のところでsimple_query_stringを使っています。

simple_query_string: 
  { query: "\"#{@condition_params[:keyword]}\"",
    fields: ['name', 'sentence'],
    default_operator: 'and',
  }

ここにあるようにキーワード検索クエリにはいくつか種類がありますが、ファイル名にアンダーバーがある場合が結構あったため、simple_query_stringを使うことにしました。

上でも書いている通りversionが2系なので、近々バージョアップをしていく予定です。その場合は、mappingの定義stringと書いているところをtextに変更するなど多少手直しが必要になりますが、バージョンを古いままにしておくわけにはいかないので、対応していくつもりです。

先生・生徒のコミニケーション機能の各メッセージに対してのキーワード検索

ここでも検索対象となる投稿本文のデータをjson形式にしてElasticsearchに入れています。データの形式はメッセージとそれに対するコメントが1対多になっています。検索時にはそのメッセージとコメントの中をみて検索キーワードに該当するものを抽出します。そのため今回はメッセージとコメントを一つのjsonに入れてElasticsearchに登録しています。
mappingの書き方としては、以下のようにします。

indexes :id,             type: 'long'
indexes :body,           type: 'text', analyzer: 'kuromoji_analyzer'
indexes :comments, type: 'nested' do
  indexes :id,           type: 'long'
  indexes :body,         type: 'text', analyzer: 'kuromoji_analyzer'
end

nestedを使うことで1対多のデータを一つのjsonとしてElasticsearchに入れることができます。
検索時にはmessageのbodyとcommentsのbodyをそれぞれみて検索するようにします。こういう形式のデータでも手軽に検索できるのはElasticsearchのような検索エンジンの利点だと思います。

バージョンアップ

この機能で使っているのはversionが5系です。最新は6系なのでバージョンアップをしなければなりません。Amaozon Elasticsearch Serviceでは簡単にアップデートできる仕組みを提供しています。

スクリーンショット 2018-12-09 12.18.28.png

ここの青い枠で囲っている「ドメインのアップグレード」からElasticsearchのバージョンアップができます。自分が試して見たところノーメンテで出来ました。

動画コンテンツのキーワード検索

こちらは私が直接担当しているものではないのですが、以前mapping定義やqueryを見たところ検索時に各要素にscore(キーワードに対するマッチ度)を付けて検索結果の並び順を導き出しています。scoreの出し方はqueryを以下のように書いてやっています。例ですが、functionsの中に独自でscoreの計算方法を独自で設定する場合は定義していきます。

        query: {
          function_score: {
            score_mode: 'sum', # functionsないのスコアの計算方法
            boost_mode: 'multiply', # クエリの合計スコアとfunctionのスコアの計算方法
            query: {
              bool: {
                must: {~~~~~~},
              }
            },
            functions: [
              {
                field_value_factor: {
                  field: "field1",
                  factor: 2,
                  modifier: "square",
                  missing: 1
                },
                weight: 5
              },
              {
                field_value_factor: {
                  field: "field2",
                  factor: 3,
                  modifier: "sqrt", # squt: ルート
                  missing: 1
                },
                weight: 2
              }
            ]
          }
        },

これだとfield1の値を2乗してfactorの値をかけます。そしてその値にweightとして5をかけます。
もう一つのfield2の値のルート値にfactorの値をかけます。そしてweightとして2をかけます。
以上の値を足し合わせ、さらにquery実行時に出たscoreの値を全てsum(足し合わせる)することで検索結果で算出されるscoreが出ます。

以上です。

今後やりたいこと

来年やりたいこととして、まずは古いElasticsearchのバージョンを上げようと思っています。6系に揃えたいと思います。
個人的にはpluginを作って機能拡張をしてみたいという気持ちがあります。間に合えば今回の記事にそれを含めたいと思っていました。が、すみません、間に合いませんでした。
その件は後日また。

10
0
1

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
10
0