そういうことだったんですね

いろいろ調べたり学んだりしたことを忘れないように書き連ねています

Rails - Tire と 全文検索エンジン Elasticsearch (2)

Rails - Tire と 全文検索エンジン Elasticsearch (1) の続きです

はじめに

今回の例は elasticsearch をバックグラウンドで動作させます。

bin/elasticsearch

で実行します。

Elasticsearch のインデックス

検索エンジンの要であるインデックスを操作します。

前回も例で示しましたが、Elasticsearchは RESTful なアプリケーションです。 クライアントは curl で行えます。ブラウザでもOKです。

REST はHTTPの以下の4種類のMETHOD(formタグで指定するアレです)から、 操作を行うものです。 Elasticsearch でのインデックスの使われ方はおおざっぱに次の通りです。

  • GET - インデックスを取得する・検索する
  • POST - インデックスデータを新規追加する
  • POST - インデックスデータを更新する
  • DELETE - インデックスデータを削除する

インデックスの作成

とあるブログ(架空)を例にします。POSTメソッドで新規作成になります。

$ curl -XPOST http://localhost:9200/blog/article -d '{
  "title": "増し増しに沈没",
  "tags" : ["Ruby","ラーメン二郎"],
  "content": "ラーメン二郎にチャレンジしました\n増し増しに撃沈\n胃薬飲んでかえります",
  "published_on": "2013-08-31T22:07:18+09:00"
}'

URL の パス名の部分が重要です。

  • blog が index になります。 RDBMS の database の概念と同じです。
  • article が type になります。 RDBMS の table の概念と同じです。

戻り値は次の通り。 キーが _id のものがこのインデックスの固有のidになります。


{"ok":true,"_index":"blog","_type":"article","_id":"UZZ-CFdLTmCce1AnDJVzmg","_version":1}

PUT メソッドを使うとidを指定しての更新(新規作成)も可能です。

$ curl -XPUT http://localhost:9200/blog/article/1 -d '{
  "title": "油は多めでないと",
  "tags" : ["Ruby","家系ラーメン"],
  "content": "久々に家系ラーメンを食べました\nやっぱり胃薬飲んでかえります",
  "published_on": "2013-08-31T22:07:18+09:00"
}'

インデックスの表示

GET メソッドを指定するとインデックスが検索できます。

$ curl -XGET http://localhost:9200/blog/article/1

検索

作成したインデックスをもとに検索を行うことができます。

$ curl -XGET http://localhost:9200/blog/_search -d '{
"query" : { 
  "term" { "content": "ラーメン" }
}
}'

こんな感じで結果が返ります

{"took":1,"timed_out":false,"_shards":{"total":5,"successful":5,"failed":0},"hits":{"total":1,"max_score":0.057534903,"hits":[{"_index":"blog","_type":"article","_id":"UZZ-CFdLTmCW6FAnDJVzmg","_score":0.057534903, "_source" : {
  "title": "増し増しに沈没",
  "tags" : ["Ruby","ラーメン二郎"],
  "content": "ラーメン二郎にチャレンジしました\n増し増しに撃沈\n胃薬飲んでかえります",
  "published_on": "2013-08-31T22:07:18+09:00"
}}]}}

このラッパーとなるクラスが Tire です。

Tire

Ruby単体でも動作しますが、Railsと組み合わせた方が力を発揮しそうです。

インストール

$ gem install tire

Ruby単体での動作

最初に tire を読み込みます。

require 'rubygems'
require 'tire'

インデックスを作成・削除・更新

Tire.index 内のメソッドで行います。

Tire.index 'post_tire' do
  delete
  create
  store title: "増し増しに沈没", tags: ["Ruby","ラーメン二郎"], content: "ラーメン二郎にチャレンジしました\n増し増しに撃沈\n胃薬飲んでかえります", published_on: Time.now
  refresh
end

検索

前項のインデックスを作成した後に検索を行います。

s =  Tire.search 'post_tire' do
  query do
    string "content:ラーメン"
  end
end
s.results.each do |document|
  puts "* title: #{document.title} content: #{ document.content } [tags: #{document.tags.join(', ')}]"
end

結果はこんな感じに出力されます。

* title: 増し増しに沈没 content: ラーメン二郎にチャレンジしました
増し増しに撃沈
胃薬飲んでかえります [tags: Ruby, ラーメン二郎]

次回は Rails との連携について書きたいと思います。

参考資料