LoginSignup
5
3

More than 5 years have passed since last update.

jruby sinatraでつくるスタンドアローンサーチエンジン

Last updated at Posted at 2015-12-23

先日のohkawaさんの記事に比べると大分カジュアルな内容になります。m(_ _)m
あれと比べると全然時間かけてません。

jruby sinatraでつくるスタンドアローンサーチエンジン

jruby sintraにelasticsearchを内蔵した簡易サーチエンジンを作ってみました。
注意) 実用的ではありません、やりたかっただけです。

sinatraで作ったオレオレサーバーにelasticsearchを組み込み
簡易REST APIから検索できるようにしてみました。

config/elasticsearch.ymlを適切に設定すれば既存のelasticsearch clusterに接続することももちろん可能です。
(そこまでするなら普通にruby api使えよって説もある)

webサーバーにはpumaを使用していて、それなりにパフォーマンスは出るはずです。

とりあえず動かす

gradleインストール

for mac

$ brew install gradle

起動

$ git clone git@github.com:shinjiikeda/jruby_embedded_elasticsearch.git
$ ./gradlew run

elasticsearch起動を確認

$ curl -XGET http://localhost:9200/

elasticsearchのendpointもそのまま使えます。

データフィード

データフィードはelasticsearchのAPIをそのまま使います。

別のターミナルから

$ cd example
$ ./import.sh

テスト

$ curl -XGET http://localhost:4567/test/type1?query=test1
{
  "took" : 12,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 1,
    "max_score" : 0.4375,
    "hits" : [ {
      "_index" : "test",
      "_type" : "type1",
      "_id" : "1",
      "_score" : 0.4375,
      "_source":{ "title" : "test1", "description": "a b c d" }
    } ]
  }
}

解説

Directoryレイアウト

config/  <- elasticsearch.ymlなどelasticsearchのコンフィグはここ
scripts/ <- ruby scriptはここ
data/    <- elasticsearchのindexはここ
plugins/ <- elasticsearchのpluginはここにいれる

ruby rest apiソース

scripts/app.rb

# encoding; utf-8

require 'java'

java_import org.elasticsearch.node.NodeBuilder
java_import org.elasticsearch.action.search.SearchResponse
java_import org.elasticsearch.action.search.SearchType
java_import org.elasticsearch.index.query.QueryBuilders
java_import org.elasticsearch.index.query.QueryStringQueryBuilder

require 'sinatra/base'
require 'json'

$node = NodeBuilder.nodeBuilder().node();
$client = $node.client();

class App < Sinatra::Base
  configure do
  end

  get '/:index/:type' do
    index = @params['index']
    type = @params['type']
    query = @params['query']
    fields = ! @params['fields'] ? ["_all"] : @params['fields'].split(/,/)
    from = @params['from'] ? @params['from'].to_i : 0
    size = @params['size'] ? @params['size'].to_i : 10

    qsq = QueryBuilders.queryStringQuery(query)
    fields.each do | f |
      qsq.field(f)
    end
    qsq.defaultOperator(QueryStringQueryBuilder::Operator::AND)

    response = $client.prepareSearch(index)
                      .setTypes(type)
                      .setSearchType(SearchType::DFS_QUERY_THEN_FETCH)
                      .setQuery(qsq)
                      .setFrom(from).setSize(size)
                      .execute()
                      .actionGet()
    response.to_s
  end

  run!
end

今回は時間もなかったのでjava apiを直で呼んでおります。
この辺は好きに加工してもらっていいと思います。
出力形式もhaml等使ってカスタマイズも簡単です。

小規模の検索サービスで既存のものを置き換えたいとか専用api作る必要あるけど、それだけのためにelasticsearchとapiをそれぞれ立てるのが面倒くさいときなどに役に立つかもしれません。

5
3
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
5
3