株式会社クリアコード > ククログ

ククログ


Ruby on RailsでPostgreSQLとPGroongaを使って日本語全文検索を実現する方法

PostgreSQLは標準機能では日本語のテキストを全文検索することはできません。PostgreSQLにPGroonga(ぴーじーるんが)という拡張機能を導入することで日本語のテキストを全文検索できるようになります。しかもPGroongaは高速です。Wikipedia日本語版のテキスト(約185万件・平均約4KB)から約2万件ヒットするような全文検索をしても0.2秒かかりません

PostgreSQLと全文検索エンジンサーバーを組み合わせて日本語全文検索を実現することもできますが、管理するサーバーが増える・SQL以外に全文検索エンジンサーバーのことを覚える必要があるなど開発・運用時のコストが高くなります。PostgreSQLだけで完結できた方が開発時も運用時も楽になります。

この記事ではRuby on Railsで作ったアプリケーションからPGroongaを使って日本語全文検索機能を実現する方法を説明します。実際にドキュメント検索システムを開発する手順を示すことで説明します。ここではCentOS 7を用いますが、他の環境でも同様の手順で実現できます。

PostgreSQLとPGroongaのインストール

まずPostgreSQLとPGroongaをインストールします。CentOS 7以外の場合にどうすればよいかはPGroongaのインストールドキュメントを参照してください。

% sudo -H rpm -ivh http://yum.postgresql.org/9.4/redhat/rhel-$(rpm -qf --queryformat="%{VERSION}" /etc/redhat-release)-$(rpm -qf --queryformat="%{ARCH}" /etc/redhat-release)/pgdg-centos94-9.4-1.noarch.rpm
% sudo -H rpm -ivh http://packages.groonga.org/centos/groonga-release-1.1.0-1.noarch.rpm
% sudo -H yum install -y postgresql94-pgroonga
% sudo -H /usr/pgsql-9.4/bin/postgresql94-setup initdb
% sudo -H systemctl enable postgresql-9.4
% sudo -H systemctl start postgresql-9.4

Rubyのインストール

CentOS 7にはRuby 2.0のパッケージがありますが、Ruby on Rails 4.2.4はRuby 2.2が必要なのでrbenvとruby-buildでRuby 2.2をインストールします。

% sudo -H yum install -y git
% git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
% git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
% echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
% echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
% exec ${SHELL} --login
% sudo -H yum install -y gcc make patch openssl-devel readline-devel zlib-devel
% rbenv install 2.2.3
% rbenv global 2.2.3

Ruby on Railsのインストール

Ruby on Railsをインストールします。

% gem install rails

ドキュメント検索システムの開発

いよいよ日本語全文検索機能を持ったドキュメント検索システムを開発します。

まずはrails newで雛形を作ります。PostgreSQLのクライアントライブラリー(pg gem)をビルドするためにpg_configコマンドがインストールされているパスをPATH環境変数に指定しています。指定しなくてもpg_configコマンドが見つかるなら指定する必要はありません。

% sudo -H yum install -y postgresql94-devel
% PATH=/usr/pgsql-9.4/bin:$PATH rails new document_search --database=postgresql
% cd document_search

therubyracer gemを有効にします。

Gemfileから次の行のコメントを外します

# gem 'therubyracer', platforms: :ruby

therubyracer gemをインストールします。

% sudo -H yum install -y gcc-c++
% bundle install

PostgreSQLに接続するユーザーを作成します。スーパーユーザー権限をつけているのはCREATE EXTENSIONを実行するにはスーパーユーザー権限が必要だからです。CREATE EXTENSIONはPGroongaを有効にするときに使います。

% sudo -u postgres -H createuser ${USER} --superuser

ユーザーを作成しPostgreSQLにデータベースを作成できるようになったのでデータベースを作成します。

% bin/rake db:create

ここまでは(ほぼ)PGroongaと関係ない手順です。アプリケーションがPostgreSQLを使う場合にはよくある手順です。

ここからはPGroongaを使う場合に特有の手順になります。

まず、データベースでPGroongaを使えるようにします。

マイグレーションファイルを作成します。

% bin/rails generate migration EnablePGroonga
      invoke  active_record
      create    db/migrate/20151109091221_enable_p_groonga.rb

db/migrate/20151109091221_enable_p_groonga.rb次のような内容にしますsearch_pathを設定しているのはPGroongaが提供している演算子をpg_catalogにある組み込みの演算子よりも優先的に使うためです。

class EnablePGroonga < ActiveRecord::Migration
  def change
    reversible do |r|
      current_database = select_value("SELECT current_database()")

      r.up do
        enable_extension("pgroonga")
        execute("ALTER DATABASE #{current_database} " +
                  "SET search_path = '$user',public,pgroonga,pg_catalog;")
      end

      r.down do
        execute("ALTER DATABASE #{current_database} RESET search_path;")
        disable_extensioin("pgroonga")
      end
    end
  end
end

これでPGroongaを使う準備が整いました。

続いて検索対象のドキュメントを格納するテーブルを作成します。

% bin/rails generate scaffold document title:text content:text
% bin/rake db:migrate

全文検索用のインデックスを作成します。

まずマイグレーションファイルを作成します。

% bin/rails generate migration AddFullTextSearchIndexToDocuments
      invoke  active_record
      create    db/migrate/20151109092724_add_full_text_search_index_to_documents.rb

db/migrate/20151109092724_add_full_text_search_index_to_documents.rb次のような内容にします。ここでusing: "pgroonga"を指定してインデックスを追加することがポイントです。

class AddFullTextSearchIndexToDocuments < ActiveRecord::Migration
  def change
    add_index(:documents, :content, using: "pgroonga")
  end
end

このマイグレーションファイルを反映します。

% bin/rake db:migrate

PostgreSQL側の準備はできたのでアプリケーション側に全文検索機能を実装します。

モデルに全文検索用のスコープを定義します。PGroongaでは@@演算子で全文検索をします。この演算子を使うと「キーワード1 OR キーワード2」のようにORを使ったクエリーを指定できます。

class Document < ActiveRecord::Base
  scope :full_text_search, -> (query) {
    where("content @@ ?", query)
  }
end

ビューにヒット件数表示機能と検索フォームをつけます。検索フォームではqueryというパラメーターに検索クエリーを指定することにします。

app/views/documents/index.html.erb:

@@ -2,6 +2,13 @@
 
 <h1>Listing Documents</h1>
 
+<p><%= @documents.count %> records</p>
+
+<%= form_tag(documents_path, method: "get") do %>
+  <%= search_field_tag "query", params["query"] %>
+  <%= submit_tag "Search" %>
+<% end %>
+
 <table>
   <thead>
     <tr>

最後に、コントローラーで全文検索を使うようにします

@@ -5,6 +5,10 @@ class DocumentsController < ApplicationController
   # GET /documents.json
   def index
     @documents = Document.all
+    query = params[:query]
+    if query.present?
+      @documents = @documents.full_text_search(query)
+    end
   end
 
   # GET /documents/1

これで日本語全文検索機能は実現できました。簡単ですね。

動作を確認するためにQiitaから検索対象のドキュメントを取得するRakeタスクを作ります

lib/tasks/data.rake:

require "open-uri"
require "json"

namespace :data do
  namespace :load do
    desc "Load data from Qiita"
    task :qiita => :environment do
      tag = "groonga"
      url = "https://qiita.com/api/v2/items?page=1&per_page=100&query=tag:#{tag}"
      open(url) do |entries_json|
        entries = JSON.parse(entries_json.read)
        entries.each do |entry|
          Document.create(title:   entry["title"],
                          content: entry["body"])
        end
      end
    end
  end
end

実行して検索対象のドキュメントを作成します。

% bin/rake data:load:qiita

http://localhost:3000/documentsにアクセスし、フォームに「オブジェクト」と日本語のクエリーを入力します。元のドキュメントは100件あり、「オブジェクト」で絞り込んで16件になっています。日本語で全文検索できていますね。

「オブジェクト」で検索

次のようにOR検索もできます。「オブジェクト」単体で検索したときの16件よりも件数が増えているのでORが効いていることがわかります。

「オブジェクト OR API」で検索

まとめ

PostgreSQLとPGroonga(ぴーじーるんが)を使ってRuby on Railsアプリケーションで日本語全文検索機能を実現する方法を説明しました。

ポイントは次の通りです。

  • enable_extension("pgroonga")
  • ALTER DATABASE SET search_path
  • add_index(using: "pgroonga")
  • where("content @@ ?", query)

開発時・運用時のことを考えてPostgreSQLベースの日本語全文検索機能の実現を検討してみてはいかがでしょうか。

おしらせ

今月の29日(11月29日)にPGroongaのイベントがあります。PGroongaに興味がでてきた方は↓のイベントページからお申し込みください。発表内容から有益な情報を得られますし、開発者に直接質問することもできます。

Groonga Meatup 2015 - Groonga | Doorkeeper

関連

タグ: Groonga
2015-11-09

Ruby on RailsでMySQLとMroongaを使って日本語全文検索を実現する方法

MySQLは先日リリースされたMySQL 5.7から標準機能で日本語のテキストを全文検索できるようになりました。逆に言うと、現在広く使われているMySQL 5.6以前では日本語のテキストを全文検索できません。MySQLにMroonga(むるんが)というストレージエンジンを導入することで日本語のテキストを全文検索できるようになります。しかもMroongaは高速です。MySQL 5.7で導入された日本語全文検索機能よりも高速です。

MySQLと全文検索エンジンサーバーを組み合わせて日本語全文検索を実現することもできますが、管理するサーバーが増える・SQL以外に全文検索エンジンサーバーのことを覚える必要があるなど開発・運用時のコストが高くなります。MySQLだけで完結できた方が開発時も運用時も楽になります。

この記事ではRuby on Railsで作ったアプリケーションからMroongaを使って日本語全文検索機能を実現する方法を説明します。実際にドキュメント検索システムを開発する手順を示すことで説明します。ここではCentOS 7を用いますが、他の環境でも同様の手順で実現できます。

MySQLとMroongaのインストール

まずMySQLとMroongaをインストールします。CentOS 7以外の場合にどうすればよいかはMroongaのインストールドキュメントを参照してください。

% sudo -H yum install -y http://packages.groonga.org/centos/groonga-release-1.1.0-1.noarch.rpm
% sudo -H yum install -y http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm
% sudo -H yum install -y mysql-community-server
% sudo -H systemctl start mysqld
% sudo -H yum install -y mysql-community-mroonga

Rubyのインストール

CentOS 7にはRuby 2.0のパッケージがありますが、Ruby on Rails 4.2.4はRuby 2.2が必要なのでrbenvとruby-buildでRuby 2.2をインストールします。

% sudo -H yum install -y git
% git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
% git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
% echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
% echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
% exec ${SHELL} --login
% sudo -H yum install -y gcc make patch openssl-devel readline-devel zlib-devel
% rbenv install 2.2.3
% rbenv global 2.2.3

Ruby on Railsのインストール

Ruby on Railsをインストールします。

% gem install rails

ドキュメント検索システムの開発

いよいよ日本語全文検索機能を持ったドキュメント検索システムを開発します。

まずはrails newで雛形を作ります。

% sudo -H yum install -y mysql-community-devel
% rails new document_search --database=mysql
% cd document_search

Active Record 4.2.4ではmysql2 gemは0.3系でなければいけないのでGemfileでバージョンを指定します。

Gemfile:

@@ -4,7 +4,7 @@ source 'https://rubygems.org'
 # Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
 gem 'rails', '4.2.4'
 # Use mysql as the database for Active Record
-gem 'mysql2'
+gem 'mysql2', '~> 0.3.20'
 # Use SCSS for stylesheets
 gem 'sass-rails', '~> 5.0'
 # Use Uglifier as compressor for JavaScript assets

バージョンを更新します。

% bundle install

therubyracer gemを有効にします。

Gemfileから次の行のコメントを外します

# gem 'therubyracer', platforms: :ruby

therubyracer gemをインストールします。

% sudo -H yum install -y gcc-c++
% bundle install

データベースを作成します。

% bin/rake db:create

ここまでは(ほぼ)Mroongaと関係ない手順です。アプリケーションがMySQLを使う場合にはよくある手順です。

ここからはMroongaを使う場合に特有の手順になります。

まず検索対象のドキュメントを格納するテーブルを作成します。

% bin/rails generate scaffold document title:text content:text

rake db:migrationする前にマイグレーションファイルを編集してストレージエンジンをMroongaに変更します。

@@ -1,6 +1,6 @@
 class CreateDocuments < ActiveRecord::Migration
   def change
-    create_table :documents do |t|
+    create_table :documents, options: "ENGINE=Mroonga" do |t|
       t.text :title
       t.text :content

このマイグレーションファイルを反映します。

% bin/rake db:migrate

全文検索用のインデックスを作成します。

まずマイグレーションファイルを作成します。

% bin/rails generate migration AddFullTextSearchIndexToDocuments
      invoke  active_record
      create    db/migrate/20151109143515_add_full_text_search_index_to_documents.rb

db/migrate/20151109143515_add_full_text_search_index_to_documents.rb次のような内容にします。ここでtype: :fulltextを指定してインデックスを追加することがポイントです。

class AddFullTextSearchIndexToDocuments < ActiveRecord::Migration
  def change
    add_index :documents, :content, type: :fulltext
  end
end

このマイグレーションファイルを反映します。

% bin/rake db:migrate

MySQL側の準備はできたのでアプリケーション側に全文検索機能を実装します。

モデルに全文検索用のスコープを定義します。MySQLで全文検索を実行するときはMATCH(...) AGAINST('...')を使います。Web検索エンジンのように「キーワード1 OR キーワード2」とORを使ったクエリーを指定できるMATCH(...) AGAINST('*D+ ...' IN BOOLEAN MODE')がオススメです。

class Document < ActiveRecord::Base
  scope :full_text_search, -> (query) {
    where("MATCH(content) AGAINST(? IN BOOLEAN MODE)", "*D+ #{query}")
  }
end

ビューにヒット件数表示機能と検索フォームをつけます。検索フォームではqueryというパラメーターに検索クエリーを指定することにします。

app/views/documents/index.html.erb:

@@ -2,6 +2,13 @@
 
 <h1>Listing Documents</h1>
 
+<p><%= @documents.count %> records</p>
+
+<%= form_tag(documents_path, method: "get") do %>
+  <%= search_field_tag "query", params["query"] %>
+  <%= submit_tag "Search" %>
+<% end %>
+
 <table>
   <thead>
     <tr>

最後に、コントローラーで全文検索を使うようにします

@@ -5,6 +5,10 @@ class DocumentsController < ApplicationController
   # GET /documents.json
   def index
     @documents = Document.all
+    query = params[:query]
+    if query.present?
+      @documents = @documents.full_text_search(query)
+    end
   end
 
   # GET /documents/1

これで日本語全文検索機能は実現できました。簡単ですね。

動作を確認するためにQiitaから検索対象のドキュメントを取得するRakeタスクを作ります

lib/tasks/data.rake:

require "open-uri"
require "json"

namespace :data do
  namespace :load do
    desc "Load data from Qiita"
    task :qiita => :environment do
      tag = "groonga"
      url = "https://qiita.com/api/v2/items?page=1&per_page=100&query=tag:#{tag}"
      open(url) do |entries_json|
        entries = JSON.parse(entries_json.read)
        entries.each do |entry|
          Document.create(title:   entry["title"],
                          content: entry["body"])
        end
      end
    end
  end
end

実行して検索対象のドキュメントを作成します。

% bin/rake data:load:qiita

http://localhost:3000/documentsにアクセスし、フォームに「オブジェクト」と日本語のクエリーを入力します。元のドキュメントは100件あり、「オブジェクト」で絞り込んで16件になっています。日本語で全文検索できていますね。

「オブジェクト」で検索

次のようにOR検索もできます。「オブジェクト」単体で検索したときの16件よりも件数が増えているのでORが効いていることがわかります。

「オブジェクト OR API」で検索

まとめ

MySQLとMroonga(むるんが)を使ってRuby on Railsアプリケーションで日本語全文検索機能を実現する方法を説明しました。

ポイントは次の通りです。

  • create_table(options: "ENGINE=Mroonga")
  • add_index(type: :fulltext)
  • where("MATCH(content) AGAINST(? IN BOOLEAN MODE)", "*D+ #{query}")

開発時・運用時のことを考えてMySQLベースの日本語全文検索機能の実現を検討してみてはいかがでしょうか。

おしらせ

今月の29日(11月29日)にMroongaのイベントがあります。Mroongaに興味がでてきた方は↓のイベントページからお申し込みください。発表内容から有益な情報を得られますし、開発者に直接質問することもできます。

Groonga Meatup 2015 - Groonga | Doorkeeper

関連:Ruby on RailsでPostgreSQLとPGroongaを使って日本語全文検索を実現する方法

タグ: Groonga
2015-11-10

Fedoraプロジェクトにてみんなでパッケージをメンテナンスするには

はじめに

以前、Fedoraプロジェクトでパッケージをリリースするための方法について書きました。

そして、次のような共同メンテナ(co-maintainer)を募集する記事も書きました。

その後、実際に共同メンテナとしてパッケージメンテナを新たに追加する機会があったので、そのときのことを紹介します。 おそらく、パッケージメンテナになる場合の最速のパターンです。

既存パッケージの共同メンテナになるまで

既存パッケージの共同メンテナになるには、次のような段取りを踏みます。

ざっくり説明すると、共同メンテナになりたい人がすることと、既存パッケージのメンテナがすることの2つがあります。

  • 共同メンテナになりたい人がすること

    • Bugzillaにアカウントを作成する
    • FAS(Fedora Account System)にアカウントを作成する
    • CLA(Contributors License Agreement)へ同意する
    • リポジトリへアクセスする公開鍵をFASアカウントに登録する
    • Proxy sponsorshipのチケットを作成してもらう(既存パッケージのメンテナに依頼すること)

ここまでが、共同メンテナになりたい人がすることです。 公開鍵等のところまでについては、冒頭で紹介した過去の記事を参照してください。

Proxy sponsorshipのチケットを作成をお願いするところまでできたら、あとはじっと待つだけです。

  • 既存パッケージのメンテナがすること
    • Proxy sponsorshipによりpackagerグループに共同メンテナとして迎えたい人を入れてもらう
    • Commit Accessを共同メンテナにしたい人に付与する

既存パッケージのメンテナがすることは上記の2つです。Proxy sponsorshipについては、後述します。

Proxy sponsorshipとは

Proxy sponsorshipとは、共同メンテナを追加するときに(packagerグループでsponsor権限をもっている人に)スポンサーになってもらうことを指します。 新規パッケージを追加するときには自身のスポンサーを探しましたが、Proxy sponsorshipの場合には「Proxy」とあるように、共同メンテナのために代理申請するところが違います。

例えば、Groongaに対するProxy sponsorshipのリクエストは次のようなチケットを作成しました。

チケットを作成するときは、コンポーネントとして「Comaintainership request」を選択して、共同メンテナに関するチケットであることを明示します。

あとは、スポンサーがつくのを待ちます。上記のチケットの場合、1日でスポンサーがついて、無事myokoymさんはpackagerグループのメンバーになりました。

Commit Accessを付与する

共同メンテナの対象者がpackagerグループに入ったら、次はCommit Accessを付与する必要があります。 packagerグループに入っただけでは、パッケージを管理しているリポジトリにコミットすることはできません。

そのため、パッケージの管理者が、共同メンテナにしたい人のFedoraアカウントに対してコミット権を付与する操作が必要です。

Fedoraプロジェクトでは、Fedora Package Databaseというのがあって、管理画面から共同メンテナに対するコミット権を管理できるようになっています。*1

pkgdbのコミット権の管理画面

コミット権を与えたら、次のアップデートを共同メンテナに出してもらいましょう。

まとめ

Fedoraプロジェクトにてみんなでパッケージをメンテナンスする方法として、既存のパッケージの共同メンテナになるというのを紹介しました。

自分の使っているパッケージでメンテナが1人しかいなかったり、新規リリースへの追従が滞っているような場合には、共同メンテナになって一緒に良くしていくのはどうでしょうか。

*1 ブランチごとに付与できるので、特定のブランチのみのメンテナを任命するという運用にすることもできる

2015-11-11

2015年11月29日開催予定のGroonga Meatup 2015の内容を紹介

全文検索エンジンGroongaは毎年いい肉の日(11月29日)にイベントを開催しています。今年も「Groonga Meatup 2015」という名前で開催予定です。

Groonga Meatup 2015の発表内容を紹介するのでおもしろそうなのがあった人はぜひお越しください。おもしろそうな内容があるけど会場まで来れないという方はインターネット配信をご利用ください。YouTubeのGroongaチャンネルでライブ配信する予定です。

なお、今回、はじめてイベントTシャツを作成しました。(オリジナルTシャツ作成サービスTMIXを提供しているspice lifeさんがスポンサーしてくれました。)

次のデザインが前面にプリントされたTシャツになります。肉々しいですね。

Groonga Meatup 2015 Tシャツ

それでは内容を紹介します。

Groonga族の今年1年のアップデートと今後の展望

Groonga Meatup 2015は2部構成になっています。第1部は開発者がGroongaとその関連プロダクトについて次のことを紹介します。

  • 特徴
  • 最新情報
  • 今後

関連プロダクトは次の通りです。

  • Mroonga:MySQLからGroongaを使うためのプロダクト。
  • PGroonga:PostgreSQLからGroongaを使うためのプロダクト。
  • Rroonga:RubyからGroongaを使うためのプロダクト。
  • Droonga:Groongaを使った分散全文検索エンジン。

第1部では次の2つの発表があります。

  • Groonga族2015
  • Turbo Selector (grn_ts) の紹介
Groonga族2015

「Groonga族2015」ではGroonga・Mroonga・PGroonga・Rroonga・Droongaについて、特徴・最新情報・今後を紹介します。現時点でGroonga族2015の資料は185ページもあります。30分の枠なのに、です。すべてを細かく説明する時間はないはずなので、30分の中では駆け足で紹介し、懇親会の時間に肉でも食べながら、参加者とやりとりしながら、細かいところを紹介する予定です。

Groongaとその関連プロダクトをキャッチアップしたい方にオススメの内容です。

Turbo Selector (grn_ts) の紹介

「Turbo Selector (grn_ts) の紹介」では開発を進めているGroongaの次期クエリー実行エンジン「grn_ts(ぐるんたす)」について紹介します。grn_tsはGroongaのカラムストアの特性をより活かしたクエリー実行エンジンになるように実装されていて、現在のクエリー実行エンジンよりも10倍速くなることもあります。

Groongaの高速化に興味のある方にオススメの内容です。なお、grn_tsについてはgrn_ts (ぐるんたす)の紹介も参照してください。

Groongaと関連プロダクトのよいところを紹介

第2部はユーザーがGroongaと関連プロダクトについて「自分がよいと思っていること」を紹介します。ユーザーがどうしてGroongaあるいは関連プロダクトを使っているかを知ることができます。自分がどのプロダクトを使うか選ぶときに参考になりそうですね。

第2部では次の8つの発表があります。

  • Mroongaをとある教育サービスで導入してみた話 - @sasata299さん
  • Rubyでプラグインを作れる分散全文検索エンジンDroonga - @KitaitiMakotoさん
  • MroongaとownCloudの良い関係 - @ukitiyanさん
  • (検討中) - 村山さん
  • Groongaをタグ検索で使う話(仮) - @naoa_yさん
  • Droongaを転職情報サイトで使ってみた話 - 瀬戸隆太さん
  • Groonga導入事例(仮) - Hiroyuki Sato(@hiroysato)さん
  • GroongaアプリケーションをDockerコンテナ化して配布する - @ongaeshiさん
Mroongaをとある教育サービスで導入してみた話 - @sasata299さん

(たぶん)ヒトメディアさんでMroongaを使ってよかったことを話してくれるはずです。(たぶん)Ruby on RailsからMroongaを使っているので、Ruby on RailsでMroongaを使ってよかったことが聞けるかもしれません。

MySQLで日本語全文検索したい人は楽しみにしてください。

Rubyでプラグインを作れる分散全文検索エンジンDroonga - @KitaitiMakotoさん

北市さんはEPUB SearcherでDroongaを使っているので、それで得られた知見をもとに話してくれるのでしょう。

Groongaを使って実装されている分散全文検索エンジンDroongaについて興味のある方は楽しみにしてください。

MroongaとownCloudの良い関係 - @ukitiyanさん

高橋さんはownCloudというオープンソースのオンラインストレージ製品にMroongaを使ってファイルの中身で全文検索できるようにする機能を追加しました。この事例はMroongaのサイトでも紹介しています。ownCloudはPHPで実装されているのでPHPからMroongaを利用することについての話も既けるかもしれません。

ownCloudに興味がある方、PHPからMroongaを使おうかと思っている方は楽しみにしてください。

(検討中) - 村山さん

村山さんはALog ConVerterというアクセスログを収集する商用のセキュリティ製品に関わっています。ALog ConVerterの最新バージョン(v7)からバックエンドのデータベースにGroongaを使っているのですが、それに関する話をしてくれるはずです。ALog ConVerterはWindows上で動く製品で、もちろんGroongaもWindows上で動いています。

WindowsでGroongaを動かすことに興味がある方は楽しみにしてください。

Groongaをタグ検索で使う話(仮) - @naoa_yさん

村上さんはかなりGroongaを使い込んでいる方です。最近、Groonga term similar pluginGroonga output utility pluginを開発していました。これらを使ってGroongaでタグ検索を実装する話をしてくれるのでしょう。

Groongaでタグ検索をしようと考えている方は楽しみにしてください。

なお、村上さんのブログ・サイトは有益な情報がたくさんあるので、一読をオススメします。

Droongaを転職情報サイトで使ってみた話 - 瀬戸隆太さん

瀬戸さんはピタジョブでどのようにDroongaを使っているかを紹介してくれます。Droongaの事例の2件目です。

Droongaに興味のある方はこちらも楽しみにしていてください。

Groonga導入事例(仮) - Hiroyuki Sato(@hiroysato)さん

佐藤さんはデータ転送ツールEnbulkGroongaプラグインを開発しています。それに関する話をしてくれるのかもしれません。(違う話かもしれません。)

Groongaにどうやってデータを入れるかに興味がある方は楽しみにしてください。(違う話だったらすみません。)

GroongaアプリケーションをDockerコンテナ化して配布する - @ongaeshiさん

おんがえしさんはMilkodeHonyomiなどRroongaを使ったアプリケーションをいくつも開発しています。最近は公式のRroonga用のDockerイメージを作成してくれました。それに関して話をしてくれるはずです。

Dockerに興味がある、簡単にRroongaを使いたいという方は楽しみにしてください。

まとめ

11月29日(今週の日曜日)開催予定のGroonga Meatup 2015の内容を紹介しました。まだ空きがあるので、興味がある話題があった方はぜひ参加してみてください。

なお、無料で懇親会に参加できます。会場提供のぐるなびさんが懇親会用の飲食物も提供してくれるからです。この機会にGroonga関連情報をゲットしてください。

2015-11-25

PostgreSQLカンファレンス2015:PGroongaの実装 #pgcon15j

PostgreSQLカンファレンス2015PGroongaの実装というセッションでPGroongaについて自慢しました。PGroongaはPostgreSQLに超高速日本語全文検索機能を追加する拡張機能です。

関連リンク:

内容

内容は基本的にPGroongaの自慢です。(amindexを実装する人向けのヒントも要所要所で入っています。)

自慢なのでPGroongaのよいところを中心に紹介しています。もちろん苦手なところもあるのですが、それはまた別の機会にしました。このセッションに参加した人の半分くらいは全文検索を使っていなかったので、どうして苦手なのかという踏み込んだ説明をすると伝わりにくくなっていたかもしれません。そういう意味で、今回はこの配分でよかったです。

今回紹介したよいところは大きくわけて次の2つです。詳細は前述のスライドを参照してください。

  • 速い
  • 全文検索のことをよく知らなくてもいい感じに日本語全文検索を実現できるようになっている

セッション前には「PGroongaをインストールしたことがある人」・「PGroongaを使ったことがある人」はほとんどいなかったのですが、セッション後にはほとんどの人が「PGroongaを使ってみよう!」という気になっていたので発表してよかったです。(セッション前後に質問をして手を挙げて回答してもらいました。)

他のセッション

PostgreSQLカンファレンス2015には他にもいろいろセッションがありました。その中でもPivotal Greenplumのセッションは参加してよかったセッションでした。

Pivotal Greenplumは外部の全文検索サーバーを使った全文検索の仕組みを独自に実現しているようだったので、セッションが終わった後に「PGroongaというPostgreSQLと親和性の高い全文検索拡張があるよ!使いませんか!?」とアピールしました。よさそうだね!という反応をもらったので、近いうちにPivotal GreenplumでもPGroongaを使った高速な全文検索機能が実装されるかもしれません。

参考:Pivotal GreenplumはPostgreSQLベースの(forkして実装した)データベースです。最近OSSになりました。(リポジトリー

まとめ

PostgreSQLカンファレンス2015でPGroongaを自慢してきました。PostgreSQLユーザーの人に知ってもらう機会ができてよかったです。主催の日本PostgreSQLユーザ会さん、ありがとうございます。

おしらせ

2015-11-29にPGroongaが使っている全文検索エンジンであるGroongaのイベント「Groonga Meatup 2015」があります。PGroongaの話題もあるのでPGroonga・Groongaに興味ある方はぜひお越しください。

タグ: Groonga
2015-11-27

Sylpheedのプラグインの作り方(2015年版)

はじめに

Sylpheedという「軽快で使いやすいオープンソースのメールソフト」があります。 以前、Sylpheed向けにプラグインを作る方法をWindows版を前提に紹介しました。

もう2年以上前の記事となり、内容の一部が若干古くなっていることから、改めてソースコードに添付されているプラグインを作る手順を紹介します。*1

対象とするSylpheedのバージョン

Sylpheedには、バージョン3.0から正式に導入されたプラグインの仕組みがあります。 このプラグインの仕組みはしばしば改訂*2されています。 そのため、本記事で対象とするSylpheedのバージョンは現在リリースされている最新の安定版である3.4.3 Windows版とします。*3 もう間もなく3.5.0が正式リリースされますが、本記事の内容はそのまま使えるはずです。

Sylpheedのプラグインでできること

Sylpheedのプラグインの仕様はプラグイン仕様として文書化されています。 基本的に以下の2つのライブラリが提供するAPIを利用して、Sylpheedと連携して動作させる仕組みになっています。

  • LibSylphメールライブラリ(libsylph)
  • プラグインインターフェースライブラリ(libsylpheed-plugin)

具体的に利用できるAPI一覧については、ソースアーカイブに含まれている libsylph/libsylph-0.defsrc/libsylpheed-plugin-0.def でエクスポートされている内容で知る事ができます。

LibSylphメールライブラリ(libsylph)では、ネットワークやメールに関する機能を利用するためのAPIが数多く提供されています。

プラグインインターフェースライブラリ(libsylpheed-plugin)では、プラグインからユーザインタフェースを制御するためのAPIが多数提供されています。 プレフィクスが syl_plugin_ とついているものが該当します。

つまり、この2つのライブラリが提供しているAPIと組み合わせてできることなら、プラグインの実装次第で何でもできるというわけです。

プラグインから利用できるシグナル

プラグインでは、シグナルと呼ばれるイベントに対応したコールバックを登録することで、ユーザの操作に応じた処理を行なわせることができます。 プラグインから利用できるシグナルは以下の通りです。

シグナルシグナルの発行タイミング
folderview-menu-popupメールの振り分けフォルダツリー表示で右クリックしたときに発行されます。
summaryview-menu-popupサマリビュー(件名等の一覧表示)で右クリックしたときに発行されます。
compose-sendメール送信を実行したときに発行されます。
compose-createdメール作成画面を表示したときに発行されます。
compose-destroyメール作成画面を閉じたときに発行されます。
textview-menu-popupメッセージビュー(メール本文を表示)で右クリックしたときに発行されます。
messageview-showメッセージビューにメールを表示したときに発行されます。
inc-mail-startメール受信開始時に発行されます。
inc-mail-finishedメール受信終了時に発行されます。
prefs-common-open全般の設定画面を表示したときに発行されます。
prefs-account-openアカウント編集画面を表示したときに発行されます。
prefs-filter-open振り分けの設定画面を表示したときに発行されます。
prefs-filter-edit-openフィルタルール編集画面を表示したときに発行されます。
prefs-template-openテンプレート設定画面を表示したときに発行されます。
plugin-manager-openプラグイン管理画面を表示したときに発行されます。

プラグインの紹介

Sylpheedで公式に提供されているプラグインには以下の2つがあります。

  • attachment_tool
  • test

ソースパッケージsylpheed-3.4.3.tar.gzもしくはsylpheed-3.4.3.tar.bz2の plugin/attachment_tool ディレクトリおよび plugin/test ディレクトリにプラグインのソース一式が含まれています。 *4

公開中のSylpheedのプラグインについては、プラグインページにいくつか有志によるプラグインが紹介されています。

attachment_tool プラグインとは

attachment_tool プラグインは Sylpheedのプラグイン紹介ページにて紹介されていますが、添付ファイルを削除するためのプラグインです。

任意のメールを選択した状態で、メニューから [ツール] - [添付ファイルを削除] を選択することで添付ファイルの削除を行うことができます。 対象がローカルフォルダである必要があるため、IMAPアカウントでは使えません。

MIMEの構造はそのまま残っているので、どんなファイルが添付されていたかという情報は失われません。 *5

test プラグインとは

test プラグインはプラグインの基本的な構造を実装したものです。test プラグインは開発者向けのため、Sylpheedのプラグイン紹介ページでは言及されていません。 Windows版ではdllとして提供されていないので、試してみるには自分でビルドする必要があります。

このプラグインは、プラグインを実装しようとするときに非常に参考になります。 プラグインが実装すべき関数やシグナルがシンプルにまとまっているからです。プラグインを作るときの雛形として使うことができます。

test プラグインの具体的な内容はソースパッケージの PLUGIN.ja.txt に記載されています。

  • プラグインのロード時に標準出力に"test plug-in loaded!"という文字列を出力する
  • フォルダの一覧を取得し、標準出力に表示する
  • Sylpheed のバージョン文字列を取得し、標準出力に表示する
  • メインウィンドウを取得し、前面に出す
  • フォルダビューの下にサブウィジェットを追加する(Testというボタンが配置されます)
  • 「ツール」メニューに「Plugin test」メニュー項目を追加する
  • 「Plugin test」メニューを選択すると、「Click this button」というボタンのみのウィンドウを表示し、クリックするとメッセージを出力する
  • アプリケーション初期化、終了、フォルダビューのコンテキストメニューポップアップ、メッセージ作成ウィンドウ作成、メッセージ作成ウィンドウ破棄のイベントを捕捉してメッセージを表示する
  • テキストビューのコンテキストメニュー表示イベントを捕捉してメニュー項目を追加する

testプラグインを作る

では、Windowsでこのtestプラグインを作ってみましょう。 まずは、Sylpheedのプラグインをビルドするための環境構築をします。

環境構築手順についてはSylpheed Win32を元に記述しています。

  1. MinGWをインストールする
  2. msys-wgetをインストールする
  3. msys-unzipをインストールする
  4. mingw32-pexportsをインストールする
  5. GTK+ Windowsバイナリ(SDK)をインストールする
  6. インポートライブラリを作成する
  7. ソースコードをダウンロード/展開する
  8. 環境変数を設定する

ここまでできると、公式で配布されているインストーラ版もしくはzipアーカイブ版で使えるプラグインが作れます。

MinGWをインストールする

SylpheedのプラグインをビルドするためのツールはMinGWのものを利用します。ここではネットワーク経由でのインストールを行うことのできるインストーラーmingw-get-setup.exeを使ってインストールします。

インストールの途中にインストールするコンポーネントを選択する箇所があります。そこでは以下を選択します。

  • mingw-developer-toolkit
  • mingw32-base
  • msys-base

以降の説明では c:\MinGW へインストールしたものとして説明します。

正しくインストールできていれば、c:\MinGW\msys\1.0\msys.bat がインストールされています。msys.bat を実行するとウィンドウが表示されます。 これ以降の説明では、msys.bat を実行して起動したシェルでの操作はプロンプトに$をつけて説明します。

コマンドラインで作業できるように、パスを通しておきましょう。

$ export PATH=/c/MinGW/bin:/bin:$PATH
msys-wgetをインストールする

パッケージのダウンロードを行うのに必要なので、msys-wgetパッケージをインストールします。

$ mingw-get install msys-wget

正しくインストールできていれば、wget --versionを実行するとバージョンが表示されます。

$ wget --version
GNU Wget 1.12 built on msys.
...以下省略...
msys-unzipをインストールする

後でzipアーカイブの展開に使うのでunzipコマンドをインストールします。 インストールには以下のコマンドを実行します。

$ mingw-get install msys-unzip

正しくインストールできていれば、unzipを引数なしで実行するとヘルプが表示されます。

$ unzip
UnZip 6.00 of 20 April 2009, by Cygwin. Original by Info-ZIP.
..以下省略...
mingw32-pexportsをインストールする

後述するインポートライブラリの作成で使うので、mingw32-pexportsパッケージをインストールします。

$ mingw-get install mingw32-pexports

正しくインストールできていれば、pexportsを引数なしで実行するとヘルプが表示されます。

$ pexports
PExports 0.44 Copyright 1988, Anders Norlander
...以下省略...
GTK+ Windowsバイナリ(SDK)をインストールする

GTK+に関しては、Sylpheed向けにSDKが用意されているので、それを使います。 以降のシェルでの作業は$HOME/sylpheedディレクトリを作業ディレクトリとします。

$ mkdir -p sylpheed
$ cd sylpheed
$ wget 'http://sylpheed.sraoss.jp/sylpheed/win32/MinGW/GTK-MinGW-SDK_20140603.zip'
$ unzip GTK-MinGW-SDK_20140603.zip

シェル上で以下のコマンドを実行します。GTK+のデモアプリケーションが起動したら正常にインストールできています。

$ $HOME/sylpheed/GTK/bin/gtk-demo.exe

以前の記事を書いていた当時には、SDKがありませんでした。 GTK+をインストールした後に、ライブラリの個別更新が必要だったので、楽になりました。

インポートライブラリを作成する

ここまでで、GTK+の環境が用意できました。 プラグインのビルドには、冒頭で説明した以下の2つのライブラリが必要です。

  • LibSylphメールライブラリ(libsylph)
  • プラグインインターフェースライブラリ(libsylpheed-plugin)

Sylpheedをソースからビルドするというのも良いですが、MinGWだとビルドには時間もかかります。*6

そこで、Sylpheed公式サイトで配布されているzipアーカイブ版を利用してこれらライブラリのインポートライブラリを作成し、シンボルの解決はそのインポートライブラリをリンクすることによって行います。 *7

$ cd $HOME
$ wget 'http://sylpheed.sraoss.jp/sylpheed/win32/sylpheed-3.4.3-win32.zip'
$ unzip sylpheed-3.4.3-win32.zip
$ cd Sylpheed-3.4.3
$ pexports libsylph-0-1.dll > libsylph-0-1.def
$ dlltool --dllname libsylph-0-1.dll --input-def libsylph-0-1.def --output-lib libsylph-0-1.a
$ pexports libsylpheed-plugin-0-1.dll > libsylpheed-plugin-0-1.def
$ dlltool --dllname libsylpheed-plugin-0-1.dll --input-def libsylpheed-plugin-0-1.def --output-lib libsylpheed-plugin-0-1.a

上記コマンドを実行して、インポートライブラリが2つ作成できていることを確認します。

  • libsylph-0-1.a
  • libsylpheed-plugin-0-1.a
ソースパッケージをダウンロード/展開する

プラグインのビルドに必要なヘッダが含まれているソースパッケージをダウンロード/展開します。

$ cd $HOME/sylpheed
$ wget 'http://sylpheed.sraoss.jp/sylpheed/v3.4/sylpheed-3.4.3.tar.gz'
$ tar xvf sylpheed-3.4.3.tar.gz
環境変数を設定する

GTK+関連で必要な環境変数の設定を行います。

$ export PATH=$PATH:$HOME/sylpheed/GTK/bin
$ export PKG_CONFIG_PATH=$HOME/sylpheed/GTK/lib/pkgconfig

pkg-configコマンドが実行できることを確認します。*8

$ pkg-config --version
0.20

以上でプラグインのビルドに必要なすべての環境が整いました。

testプラグインをビルドする

次に、展開したソースコードのtestプラグインのディレクトリへと移動し、以下のようにしてプラグインをビルドします。

$ cd $HOME/sylpheed/sylpheed-3.4.3/plugin/test
$ gcc -shared -o test.dll test.c -I../../libsylph -I../../src `pkg-config --cflags gtk+-2.0` `pkg-config --libs gtk+-2.0` $HOME/Sylpheed-3.4.3/libsylph-0-1.a $HOME/Sylpheed-3.4.3/libsylpheed-plugin-0-1.a

test.dllがビルドできたら、以下のようにしてプラグインをインストールします。 *9

$ cp test.dll /c/Users/(ユーザー名)/AppData/Roaming/Sylpheed/plugins

あるいは、zipアーカイブ版の plugins ディレクトリにコピーするのでもよいです。

Sylpheed.exeを実行し、アプリケーションを起動します。

メニューにある [設定] - [プラグインの管理] から test プラグインがリスト登録されているはずです。

おまけ

SylpheedのWindows版のzipをもとに、Linux上でプラグインをクロスコンパイルすることもできます。

Linuxの場合、pexportsの代替としてgendefというmingw-w64-toolsパッケージ *10に含まれているツールをつかってインポートライブラリを作成します。

% gendef libsylph-0-1.dll

これでインポートライブラリができたら、コンパイルしましょう。SDKに含まれる.pcファイルはプレフィクスとして/targetを前提としているのでシンボリックリンクを張っておくとよいでしょう。*11

ここまで準備できたら、あとは次の手順でビルドするだけです。

% i686-w64-mingw32-gcc -c test.c -I../../libsylph -I../../src `pkg-config --cflags glib-2.0` `pkg-config --cflags gtk+-2.0`
% i686-w64-mingw32-gcc -shared -o test.dll test.c -I../../libsylph -I../../src `pkg-config --cflags gtk+-2.0` `pkg-config --libs gtk+-2.0` $HOME/work/sylpheed/mingw/Sylpheed-3.4.3/libsylph-0-1.dll.a $HOME/work/sylpheed/mingw/Sylpheed-3.4.3/libsylpheed-plugin-0-1.dll.a

test.dllをWindowsのプラグインディレクトリへとコピーしてあげれば、動作します。

まとめ

Windows版のSylpheed 3.4.3向けにプラグインを作る方法を紹介しました。 Windows版は長らくバンドルしているGTK+のバージョンが古く、公式版に合わせたプラグインを開発しようとすると新しめの便利なGLib/GTK+のAPIがことごとく使えないという問題がありましたが、現在ではそれも解消されています。

一度プラグインを作る環境さえ整えてしまえば、Windowsであっても*12プラグインを作るのはそれほど難しいことではありません。 test プラグインよりも、もう少しだけ複雑なものについては、Sylpheedのプラグインの作り方で紹介しています。 「メール送信時に本文のプレビューと、送信可否の問い合わせを行うプラグイン」として、サンプルコードをまじえて解説しています。

これからはじめる人は参考にしてみてください。

*1 この記事を書くきっかけは、IMAP IDLE/NOTIFYに対応したsylpheed-imap-notifyというプラグインで、Windows版が欲しいと言っている人がいたため。実際にはプラグインが非公開のAPIを使っていたため、Windows版の提供は難しいことがわかった。

*2 インタフェースバージョンのことを指す。

*3 Windows版特有の内容を除いては、Linuxなどでもその知識を生かしてプラグインを開発することができます。

*4 インストーラ版およびzipアーカイブ版にはソースは含まれていません。

*5 アイコン等が変わらないので、添付ファイルが削除されていることは添付ファイルのサイズ等から判断します。

*6 プラグインを作りたいだけなら、ソースからビルドする必要はない。独自ビルドする必要があるのは、エクスポートされていないシンボルをプラグインからどうしても使いたいときに限られる。

*7 すでにお使いのzipアーカイブ版もしくはインストール版のバイナリがあれば、改めてダウンロードしなくても既存のものを使うのでも構いません。その場合は適宜読み替えてください。

*8 pkg-configはGTK+に含まれています。

*9 ユーザー名は各自読み替えてください。

*10 Debianの場合。他のディストリビューションの場合は適宜読みかえてください。

*11 atk.pcだけ/devel以下を前提としているので、その場合修正する必要があります。

*12 GTK+の知識さえあればという条件がつく

2015-11-30

«前月 最新記事 翌月»
タグ:
年・日ごとに見る
2008|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|