Ruby(または Ruby on Rails)から、リモート(HTTP)接続で Groonga を利用する

前回の記事:CentOS 6.4(仮想環境)にMySQL 5.5 と Groonga 4.0 を環境構築、Web アプリケーションから接続する。

今回の記事では、Ruby(または Ruby on Rails)から、リモート接続先の Groonga を利用する方法を紹介します。
上記「前回の記事」の内容が、前提となる構成ですので、よろしければこちらもご参照ください。

既存のソリューションについて

※ 2014/09/30 この項の内容について、コメント欄にてご指摘を頂きました。
それの内容を元に、一部訂正をしております。

Groonga を Ruby から利用するためのソリューションを提供しているプロジェクトとして、
ラングバプロジェクト」というものがあります。
この中に、今回使えるものがないか? 少し調べてみました。

「Rroonga(るるんが)」

これは「Groongaの機能をRubyから利用するためのライブラリ」という風に解説されています。
ただ、少し使ってみたところ、リモート(HTTP)接続することはできないのかな?という感じでした。
後ほど、コメント欄にて「kou 様」に下記のようにご指摘いただきました。

RroongaはローカルのGroongaデータベースを直接操作するライブラリーなので
リモートのGroongaoサーバーに接続する機能はありません!

なるほど。。
というわけで、リモート接続したいという意味ではちょっと使うことができなさそうです。

「ActiveRroonga」

もうひとつのこっちはどうかな?ということで少し調べてみました。

「ActiveRroonga」に関しても「kou 様」にご指摘いただいた内容がわかりやすかったので、
失礼ながらこちらも転載させていただきます <(_ _)>

ActiveGroongaはRroongaをRailsで使いやすくするラッパーです。
多くのことはRroongaでやっているのでActiveGroongaはあんまりやることはありません。
Railsがバージョンアップしたときに動かなくなったら対応するくらいです。

なので、あんまり更新がありません。
ActiveGroongaはRroongaのラッパーなのでやはりローカルのGroongaデータベースを操作するためのものです。
リモートのGroongaサーバーにアクセスするためのものではありません。

ありがとうございます m(_ _)m

「groonga-client gem」

こちらも教えていただいたものですが、こちらの gem はリモート接続に対応しています。

Groonga-client is a client for groonga (http://groonga.org/) implemented with pure ruby.

Groonga-client gem supports HTTP or GQTP (Groonga Query Transfer Protocol) as the protocol using a client. You can use it without groonga package.

Groonga をリモート接続(HTTP)で使う処理を、自分で書くことにした

結局、自分で書くことにしました。(そんなに大した処理でもなさそうだったので)
大雑把に、次のようなコードです。
ruby 2.0 系で動作確認済み)

groonga_connection.rb
require "yaml"
require "json"
require "net/http"

# Groonga へのアクセスを提供するクラス
class GroongaConnection

  FILEPATH = "config/groonga.yml"

  # 初期化
  def initialize
    # 設定ファイルの内容
    @config = nil

    if File.exist?(FILEPATH)
      open(FILEPATH) do |f|
        str = f.read

        @config = YAML.load(str)
        @config.freeze
      end
    end
  end

  # コマンド実行
  def command(command_str, params = {}, post_body = nil)
    # 環境を決定
    config = @config["development"]

    # GET or POST?
    if post_body.nil?
      # 結果を取得
      response = Net::HTTP.get(config["host"], "/d/" + command_str + build_url_params(params), config["port"])
      @latest_response = JSON.parse(response)
    else
      uri = URI("http://" + config["host"] + ":" + config["port"].to_s + "/d/" + command_str + build_url_params(params))

      request = Net::HTTP::Post.new(uri)
      request.body = post_body
      request.content_type = "application/json"

      response = Net::HTTP.start(uri.hostname, uri.port) do |http|
        http.request(request)
      end

      @latest_response = response.body
    end
  end

  # ハッシュ値からURLパラメータを組み立てる
  def build_url_params(params)
    ret = ""

    # params が存在している場合は、URLパラメータを組み立てる
    unless params.empty?
      ret = "?"

      params.each do |key, value|
        ret += key.to_s + "=" + value.to_s + "&"
      end

      ret.chop!
    end

    ret
  end

  # 最後に実行したコマンドの結果を返す
  def latest_response
    @latest_response
  end

end
config/groonga.yml

このファイルにはリモート接続情報を記述します

# Groonga 環境設定
development:
  host: 192.168.1.1 # 任意の接続先
  port: 10041 # 任意のポート

GroongaConnection クラスの使い方

Groonga の status を実行してみます。

# インスタンス生成
groonga = GroongaConnection.new
# "status" 実行
groonga.command("status")
# => [[0,1411798109.95856,0.000993490219116211],{"alloc_count":162,"starttime":1411798083,"uptime":26,"version":"4.0.5","n_queries":0,"cache_hit_rate":0.0,"command_version":1,"default_command_version":1,"max_command_version":2}]

select コマンドはこんな感じ

groonga = GroongaConnection.new
groonga.command("select", {:table => "Articles"})

load は、ユーザー入力された非常に大きなデータが渡される可能性があるので、GET リクエストではなく POST リクエストで渡します。第3引数は、POST の content body として使われます。

groonga = GroongaConnection.new
groonga.command("load", {:table => "Articles"}, '[{"_key": 1, "title": "hoge", "body": "piyo"}]')


あとは、いろいろアレンジ・改良してお試しくださいませ。