- 更新日: 2014年5月20日
- Elasticsearch
Elasticsearch を Ruby から使う
Rails アプリケーションで全文検索を行うために、試しはじめた Elasticsearch ですが、ようやく Ruby から使う段階までたどり着きました。下記の記事内容がこれまで行った作業で、今回作業を行う Ruby から使うための前提となります。
ElasticsearchのインストールとCSVからのデータ挿入 | EasyRamble
Elasticsearchのクエリとフィルターで簡単な検索を試す例 | EasyRamble
ElasticsearchにMySQLからデータ挿入、JDBC River Pluginのインストールと使い方 | EasyRamble
Rails アプリで使用するとは言いましても、とりあえず検索機能のみ利用する予定ですので、今回は elasticsearch-ruby のクライアントを利用します。
もう一歩踏み込んで、Elasticsearch のデータを ActiveModel/ActiveRecord のオブジェクトとして扱うために、Rails と Elasticsearch を統合させて使いたい場合は、以下の elasticsearch-rails という gem を利用できます。こちらはいずれ余力がある時に試してみたい。
https://github.com/elasticsearch/elasticsearch-rails
elasticsearch-ruby のインストール
では早速 elasticsearch-ruby をインストールします。
Gemfile
1 |
gem 'elasticsearch' |
インストール
1 2 3 |
$ bundle install |
elasticsearch 起動。
1 2 3 |
$ elasticsearch |
pry で Ruby からの Elasticsearch 検索を試す
ElasticsearchのインストールとCSVからのデータ挿入 | EasyRamble で入れたライブドアグルメの restaurants.csv からインデックスさせた、Elasticsearch の ldgourmet/restaurant を検索の対象として使用します。
まずは、Elasticsearch にアクセスするためのクライアント・インスタンスを生成。
1 2 3 4 5 6 7 |
$ bundle exec rails c pry(main)> client = Elasticsearch::Client.new log: true => #<Elasticsearch::Transport::Client:0x007fc25962ec38 @transport= ... |
id が 5 の情報を取得。
1 2 3 4 5 6 7 8 9 10 11 12 |
pry(main)> client.get index: 'ldgourmet', type: 'restaurant', id: 5 2014-05-19 16:06:12 +0900: GET http://localhost:9200/ldgourmet/restaurant/5 [status:200, request:0.070s, query:n/a] 2014-05-19 16:06:12 +0900: < {"_index":"ldgourmet","_type":"restaurant","_id":"5","_version":1,"found":true, "_source" : { "id": "5", "name": "クレソン", "property": "自由が丘本店", "alphabet": "", "name_kana": "くれそん", ... |
結果は、Ruby のハッシュで返されます。
name フィールドに’焼肉’が含まれるお店を検索。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
pry(main)> client.search index: 'ldgourmet', body: { query: { match: { name: '焼肉' } } } 2014-05-19 16:08:02 +0900: GET http://localhost:9200/ldgourmet/_search [status:200, request:0.046s, query:0.022s] 2014-05-19 16:08:02 +0900: > {"query":{"match":{"name":"焼肉"}}} 2014-05-19 16:08:02 +0900: < {"took":22,"timed_out":false,"_shards":{"total":5,"successful":5,"failed":0},"hits":{"total":4029,"max_score":5.009488,"hits":[{"_index":"ldgourmet","_type":"restaurant","_id":"390722","_score":5.009488, "_source" : { "id": "390722", "name": "焼肉 激", "property": "", "alphabet": "", "name_kana": "やきにく げき", ... |
新しくデータをインデックスさせる。
1 2 3 4 5 6 7 8 9 10 11 |
pry(main)> client.index index: 'ldgourmet', type: 'restaurant', id: 999999, body: { name: "新規オープンのお店" } 2014-05-19 16:14:45 +0900: PUT http://localhost:9200/ldgourmet/restaurant/999999 [status:201, request:0.294s, query:n/a] 2014-05-19 16:14:45 +0900: > {"name":"新規オープンのお店"} 2014-05-19 16:14:45 +0900: < {"_index":"ldgourmet","_type":"restaurant","_id":"999999","_version":1,"created":true} => {"_index"=>"ldgourmet", "_type"=>"restaurant", "_id"=>"999999", "_version"=>1, "created"=>true} |
確認。
1 2 3 4 5 6 7 8 9 10 11 |
pry(main)> client.get index: 'ldgourmet', type: 'restaurant', id: 999999 2014-05-19 16:19:02 +0900: GET http://localhost:9200/ldgourmet/restaurant/999999 [status:200, request:0.025s, query:n/a] 2014-05-19 16:19:02 +0900: < {"_index":"ldgourmet","_type":"restaurant","_id":"999999","_version":1,"found":true, "_source" : {"name":"新規オープンのお店"}} => {"_index"=>"ldgourmet", "_type"=>"restaurant", "_id"=>"999999", "_version"=>1, "found"=>true, "_source"=>{"name"=>"新規オープンのお店"}} |
データの update も index メソッドで行える模様。
1 2 3 4 5 6 7 8 9 10 11 |
pry(main)> client.index index: 'ldgourmet', type: 'restaurant', id: 999999, body: { name: "elasticなラーメン屋さん" } 2014-05-19 16:23:46 +0900: PUT http://localhost:9200/ldgourmet/restaurant/999999 [status:200, request:0.033s, query:n/a] 2014-05-19 16:23:46 +0900: > {"name":"elasticなラーメン屋さん"} 2014-05-19 16:23:46 +0900: < {"_index":"ldgourmet","_type":"restaurant","_id":"999999","_version":2,"created":false} => {"_index"=>"ldgourmet", "_type"=>"restaurant", "_id"=>"999999", "_version"=>2, "created"=>false} |
確認。
1 2 3 4 5 6 7 8 9 10 11 |
pry(main)> client.get index: 'ldgourmet', type: 'restaurant', id: 999999 2014-05-19 16:23:54 +0900: GET http://localhost:9200/ldgourmet/restaurant/999999 [status:200, request:0.003s, query:n/a] 2014-05-19 16:23:54 +0900: < {"_index":"ldgourmet","_type":"restaurant","_id":"999999","_version":2,"found":true, "_source" : {"name":"elasticなラーメン屋さん"}} => {"_index"=>"ldgourmet", "_type"=>"restaurant", "_id"=>"999999", "_version"=>2, "found"=>true, "_source"=>{"name"=>"elasticなラーメン屋さん"}} |
削除。
1 2 3 4 5 6 7 8 9 10 |
pry(main)> client.delete index: 'ldgourmet', type: 'restaurant', id: 999999 2014-05-19 16:36:35 +0900: DELETE http://localhost:9200/ldgourmet/restaurant/999999 [status:200, request:0.026s, query:n/a] 2014-05-19 16:36:35 +0900: < {"found":true,"_index":"ldgourmet","_type":"restaurant","_id":"999999","_version":3} => {"found"=>true, "_index"=>"ldgourmet", "_type"=>"restaurant", "_id"=>"999999", "_version"=>3} |
確認。
1 2 3 4 5 6 7 |
pry(main)> client.get index: 'ldgourmet', type: 'restaurant', id: 999999 2014-05-19 16:36:55 +0900: GET http://localhost:9200/ldgourmet/restaurant/999999 [status:404, request:0.002s, query:n/a] 2014-05-19 16:36:55 +0900: < {"_index":"ldgourmet","_type":"restaurant","_id":"999999","found":false} 2014-05-19 16:36:55 +0900: [404] {"_index":"ldgourmet","_type":"restaurant","_id":"999999","found":false} Elasticsearch::Transport::Transport::Errors::NotFound: [404] {"_index":"ldgourmet","_type":"restaurant","_id":"999999","found":false} |
熊本の焼肉屋さんを検索。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
pry(main)> client.search index: 'ldgourmet', body: { query: { pry(main)* simple_query_string: { pry(main)* fields: ["_all"], pry(main)* query: "熊本 焼肉", pry(main)* default_operator: "and" pry(main)* } pry(main)* } pry(main)* } 2014-05-19 17:04:05 +0900: GET http://localhost:9200/ldgourmet/_search [status:200, request:0.044s, query:0.012s] 2014-05-19 17:04:05 +0900: > {"query":{"simple_query_string":{"fields":["_all"],"query":"熊本焼肉","default_operator":"and"}}} 2014-05-19 17:04:05 +0900: < {"took":12,"timed_out":false,"_shards":{"total":5,"successful":5,"failed":0},"hits":{"total":21,"max_score":1.1293696,"hits":[{"_index":"ldgourmet","_type":"restaurant","_id":"326302","_score":1.1293696, "_source" : { "id": "326302", "name": "焼肉 なべしま", "property": "熊本インター店(他多数)", "alphabet": "", "name_kana": "やきにくなべしま", ... |
21件見つかりました。
以上ですが、Ruby 用の elasticsearch の gem を試しに使いましたところ、Ruby から Elasticsearch の検索、インデックスへの新規作成、更新、削除が恐ろしいほど簡単に行えます。ActiveModel, ActiveRecord と Elasticsearch を統合させずに、Elasticsearch の index を検索するだけの目的であれば、この elasticsearch-ruby を用いる方法で十分かと思います。
実践で使う場合に備えて、もう少しセキュリティ面のことを調べる予定です。次回は、elasticsearch-ruby 利用時に、外部入力された文字列のエスケープについて記事を書く予定です。
ES_HOME/config/elasticsearch.yml のセッティングに関しても調べないといけない。
- – 参考リンク –
- Elasticsearch.org Release The Clients! Ruby, Python, PHP, Perl | Blog | Elasticsearch
- elasticsearch-ruby
- https://github.com/elasticsearch/elasticsearch-ruby
- Elasticsearch の関連記事
- CentOS6にElasticsearchをインストールしMySQLからデータをインポート
- Rails で jQuery を使って Elasticsearch 全文検索による検索文字をハイライトさせる
- elasticsearch-ruby でトークナイザーを指定してトークン分割
- elasticsearch-ruby で外部入力から検索時の json 用文字列のエスケープ処理
- ElasticsearchにMySQLからデータ挿入、JDBC River Pluginのインストールと使い方
- Elasticsearchのクエリとフィルターで簡単な検索を試す例
- ElasticsearchのインストールとCSVからのデータ挿入
Leave Your Message!