elasticsearchが使えるようになった。次はインデックスを構築する。
特定テーブル内の情報だけ検索できればいいなら簡単だけど、そんなイージーな事例はそうない。
たとえば「ArticleはUserにbelongs_toで、Articleを所有しているユーザー名でも検索できるようにしたい」とか、普通にあると思う。リレーショナルデータベースってそういうものでしょう。
そこで、こういう状況を仮定して考えてみる。
Articleというモデルがある。
このうち、id, title, bodyという3つの属性を検索対象フィールドとしたい。(idは単なる数値、titleとbodyは日本語の文章である。)
また、ArticleはUserに所有されている。
Userはfirst_name, last_name, nicknameという3つの属性を持っている。このfirst_nameとlast_nameを結合したuser_nameとuser_nicknameでも対応するArticleを検索できるようにする。(user_nicknameはUserのnickname属性を参照すればよく、user_fullnameはUserのuser_fullnameというメソッドで取得できるものとする。)
単一モデルの属性だけを検索対象フィールドとするのではなく、リレーションをまたぐ場合は、まずas_indexed_jsonというメソッドを実装する必要がある。
このas_indexed_jsonというのはas_jsonメソッドとほぼ同じで、レコードをjsonでシリアライズするメソッドである。elasticsearchはインデックスを構築する際に、as_indexed_jsonメソッドで返されるjsonに含まれている属性だけを見る。なので属性を検索対象フィールドにするにはその属性をas_indexed_jsonの戻り値に含めることが必要条件となる。
やることは簡単で、as_indexed_json内部でas_jsonを呼び、このとき含めたい属性をincludeするだけ。
マッピングを自動的に行う設定にしておけばこれだけで一応検索可能になるはず。
とはいえ、この自動マッピングは使い物にならない。というわけで、自動マッピングは無効化して自分でマッピングを書く必要がある。
今回は「どのフィールドにどのアナライザーを適応するか」は考えたくないし、まだよくわかっていないので無視。単にこうかけばいいんだ~という程度で。特にsnowballというのは例として載せただけで、適切なのか全く調べてない
。
user_*はuser以下にネストされているが、マッピングの設定も単にネストするだけ。ちょっと調べると'nested'というオプションがあるという情報が出てきたけど、ここでは不要。じゃあどんなときに必要になるの?思ったら、公式ドキュメントを読もう。
これでインデックスをを構築する準備は完了。