GROONGA(1)

NAME
groonga - groongaのドキュメント

•   news

GROONGAの特徴

  groonga の概要

groonga は転置索引を用いた高速・高精度な全文検索エンジンであり、登録された文書をすぐに検索結果に反映できます。また、参照をブロックせずに更新できることから、即時更新の必要なアプリケーションにおいても高い性能を発揮します。

全文検索エンジンとして開発された groonga ですが、独自のカラムストアを持つ列指向のデータベースとしての側面も持っています。そのため、MySQL や PostgreSQL など、既存の代表的なデータベースが苦手とする集計クエリを高速に処理できるという特徴があり、組み合わせによって弱点を補うような使い方もできます。

groonga の基本機能は C ライブラリとして提供されていますが、MySQL や PostgreSQL と連携させたり、Ruby から呼び出したりすることもできます。そのため、任意のアプリケーションに組み込むことが可能であり、多様な使い方が考えられます。 興味のある方は 利用例 をご覧ください。

  全文検索と即時更新

一般的なデータベースにおいては、追加・削除などの操作がすぐに反映されます。一方、全文検索においては、転置索引が逐次更新の難しいデータ構造であることから、文書の追加・削除に対応しないエンジンが少なくありません。

これに対し、転置索引を用いた全文検索エンジンでありながら、groonga は文書を短時間で追加・削除することができます。その上、更新しながらでも検索できるという優れた特徴を持っているため、全文検索エンジンとしてはとても柔軟性があります。また、複数の転置索引を統合するような重い処理を必要としないので、安定して高い性能を発揮することが期待できます。

  カラムストアと集計クエリ

現代は、インターネットを情報源とすれば、いくらでも情報を収集できる時代です。しかし、膨大な情報から有益な情報を引き出すのは困難であり、多面的な分析による試行錯誤が必要となります。たとえば、日付や時間帯により絞り込んでみたり、地域により絞り込んでみたり、性別や年齢により絞り込んでみたりすることでしょう。そして、そのようなときに便利な存在が集計クエリです。

集計クエリとは、指定したカラムの値によってレコードをグループ化し、各グループに含まれるレコードの数を求めるクエリです。たとえば、地域の ID を格納しているカラムを指定すれば、地域毎のレコード数が求まります。日付のカラムを指定したときの出力をグラフ化すれば、レコード数の時間変化を視覚化することができます。さらに、地域による絞り込みと日付に対する集計クエリを組み合わせれば、特定の地域におけるレコード数の時間変化を視覚化ことも可能です。このように、尺度を自由に選択して絞り込み・集計できることは、膨大な情報を扱う上でとても重要になります。

groonga が集計クエリを高速に処理できる理由は、データベースの論理構造にカラムストアを採用しているからです。集計クエリが参照するのは指定されたカラムのみであるため、カラム単位でデータを格納する列指向のデータベースでは、必要なカラムのみを無駄なく読み出せることが利点となります。一方、レコード単位でデータを格納する行指向のデータベースでは、隣接するカラムをまとめて読み出してしまうことが欠点となります。

  転置索引とトークナイザ

転置索引は大規模な全文検索に用いられる伝統的なデータ構造です。転置索引を用いた全文検索エンジンでは、文書を追加するときに索引語を記録しておき、検索するときはクエリを索引語に分割して出現文書を求めます。そのため、文書やクエリから索引語を抜き出す方法が重要になります。

トークナイザは、文字列から索引語を抜き出すモジュールです。日本語を対象とする全文検索においては、形態素を索引語として抜き出す方式と文字 N-gram を抜き出す方式のいずれか、あるいは両方を用いるのが一般的です。形態素方式は検索時間や索引サイズの面で優れているほか、検索結果に不要な文書が含まれにくいという利点を持っています。一方、N-gram 方式には検索漏れが発生しにくいという利点があり、状況によって適した方式を選択することが望ましいとされています。

groonga は形態素方式と N-gram 方式の両方に対応しています。初期状態で利用できるトークナイザは空白を区切り文字として用いる方式と N-gram 方式のみですが、形態素解析器 MeCab を組み込んだときは MeCab による分かち書きの結果を用いる形態素方式が有効になります。トークナイザはプラグインとして追加できるため、特徴的なキーワードのみを索引語として採用するなど、独自のトークナイザを開発することが可能です。

  共有可能なストレージと参照ロックフリー

CPU のマルチコア化が進んでいるため、同時に複数のクエリを実行したり、一つのクエリを複数のスレッドで実行したりすることの重要性はますます高まっています。

groonga のストレージは、複数のスレッド・プロセスで共有することができます。また、参照ロックフリーなデータ構造を採用しているため、更新クエリを実行している状況でも参照クエリを実行することができます。参照クエリを実行できる状態を維持しながら更新クエリを実行できるので、リアルタイムなシステムに適しています。さらには、MySQL を介して更新クエリを実行している最中に groonga の HTTP サーバを介して参照クエリを実行するなど、多彩な運用が可能となっています。

  位置情報（緯度・経度）検索

GPS に代表される測位システムを搭載した高機能な携帯端末の普及などによって、位置情報を扱うサービスはますます便利になっています。たとえば、近くにあるレストランを探しているときは、現在地からの距離を基準として検索をおこない、検索結果を地図上に表示してくれるようなサービスが便利です。そのため、位置情報検索を高速に実現できることが重要になっています。

groonga では転置索引を応用して高速な位置情報検索を実現しています。矩形・円による範囲検索に対応しているほか、基準点の近くを優先的に探索させることができます。また、距離計算をサポートしているので、位置情報検索の結果を基準点からの距離によって整列することも可能です。

  groonga ライブラリ

Groonga の基本機能は C ライブラリとして提供されているので、任意のアプリケーションに組み込んで利用することができます。C/C++ 以外については、Ruby から groonga を利用するライブラリなどが関連プロジェクトにおいて提供されています。詳しくは 関連プロジェクト を参照してください。

  groonga サーバ

groonga にはサーバ機能があるため、レンタルサーバなどの新しいライブラリをインストールできない環境においても利用できます。対応しているのは HTTP, memcached binary プロトコル、およびに groonga の独自プロトコルである gqtp です。サーバとして利用するときはクエリのキャッシュ機能が有効になるため、同じクエリを受け取ったときは応答時間が短くなるという特徴があります。

  groonga ストレージエンジン

groonga は独自のカラムストアを持つ列指向のデータベースとしての側面を持っていますが、既存の RDBMS のストレージエンジンとして利用することもできます。たとえば、groonga をベースとする MySQL のストレージエンジンとして mroonga が開発されています。mroonga は MySQL のプラグインとして動的にロードすることが可能であり、groonga のカラムストアをストレージとして利用したり、全文検索エンジンとして groonga を MyISAM や InnoDB と連携させたりすることができます。groonga 単体での利用、およびに MyISAM, InnoDB との連携には一長一短があるので、用途に応じて適切な組み合わせを選ぶことが大切です。詳しくは 関連プロジェクト を参照してください。

インストール

このセクションではgroongaのインストール方法を環境毎に説明します。主要なプラットフォームにはパッケージがあります。自分でgroongaをビルドするよりもパッケージを使うことを推奨します。しかし、心配しないでください。ソースからgroongaをビルドするためのドキュメントもあります。

32-bit用と64-bit用のパッケージを配布していますが、サーバ用途には64-bitパッケージを利用することをオススメします。32-bit用パッケージはテスト用か開発用にだけ使って下さい。32-bit用パッケージを使った場合は、中程度のサイズのデータでもメモリ不足エラーになることがあります。

  Windows

このセクションではWindows上でgroongaをインストールする方法を説明します。groongaをインストールするにはzipパッケージを展開する方法とインストーラーを実行する方法があります。

32-bit用と64-bit用のパッケージを配布していますが、サーバ用途には64-bitパッケージを利用することをオススメします。32-bit用パッケージはテスト用か開発用にだけ使って下さい。32-bit用パッケージを使った場合は、中程度のサイズのデータでもメモリ不足エラーになることがあります。

  インストーラー

32-bit環境の場合は、x86のバイナリをpackages.groonga.orgからダウンロードしてください。

コマンドラインの操作でバイナリをダウンロードすることができます。

コマンドプロンプト cmd.exe を起動し、x86バイナリをブラウザを使ってダウンロードします。:

> "c:\\Program Files\\Internet Explorer\\iexplore.exe" http://packages.groonga.org/windows/groonga/groonga-3.0.0-x86.exe

その後、バイナリを実行します。

64-bit環境の場合は、x64のバイナリをpackages.groonga.orgからダウンロードしてください。

コマンドプロンプト cmd.exe を起動し、x64バイナリをブラウザを使ってダウンロードします。:

> "c:\\Program Files\\Internet Explorer\\iexplore.exe" http://packages.groonga.org/windows/groonga/groonga-3.0.0-x64.exe

その後、バイナリを実行します。

スタートメニュー内に /reference/executables/groonga 用のコマンドプロンプトがインストールされるのでそれを使ってください。

  zip

32-bit環境の場合は、x86のzipアーカイブをpackages.groonga.orgからダウンロードしてください。

コマンドラインの操作でバイナリをダウンロードすることができます。

コマンドプロンプト cmd.exe を起動し、x86バイナリをブラウザを使ってダウンロードします。:

> "c:\\Program Files\\Internet Explorer\\iexplore.exe" http://packages.groonga.org/windows/groonga/groonga-3.0.0-x86.zip

その後、アーカイブを展開します。

64-bit環境の場合は、x64のzipアーカイブをpackages.groonga.orgからダウンロードしてください。

コマンドプロンプト cmd.exe を起動し、x64バイナリをブラウザを使ってダウンロードします。:

> "c:\\Program Files\\Internet Explorer\\iexplore.exe" http://packages.groonga.org/windows/groonga/groonga-3.0.0-x64.zip

その後、アーカイブを展開します。

/reference/executables/groonga は bin フォルダーにあります。

  ソースからビルド

まずWindows上でgroongaをビルドするために必須のツールをインストールします。以下が必須のツールです。

•   Microsoft Visual Studio 2010 Express

•   CMake

    zipアーカイブをpackages.groonga.orgからダウンロードしてください。

    コマンドラインの操作でzipソースファイルをダウンロードすることができます。

    Microsoft Visual Studio 2010 Expressがインストールする Visual Studio コマンド プロンプト (2010) を実行して、groongaのソースをブラウザでダウンロードしてください:

    > cd c:\Users\%USERNAME%\Downloads
    > "c:\\Program Files\\Internet Explorer\\iexplore.exe" http://packages.groonga.org/source/groonga/groonga-3.0.0.zip

    その後、アーカイブを展開します。

    groongaのソースフォルダへと移動します:

    > cd c:\Users\%USERNAME%\Downloads\groonga-3.0.0

    cmake でビルドオプションを設定します。以下のコマンドラインは64-bit用のgroongaをビルドするためのものです。32-bit用のgroongaをビルドする場合は代わりに -G "Visual Studio 10" パラメーターを指定してください:

    groonga-3.0.0> cmake . -G "Visual Studio 10 Win64" -DCMAKE_INSTALL_PREFIX=C:\groonga

    Visual C++ 2010 Expressでビルドします:

    groonga-3.0.0> msbuild groonga.sln /p:Configuration=Release

    Visual C++ 2010 Expressでビルドします:

    groonga-3.0.0> msbuild groonga.sln /p:Configuration=Release /t:Install

    Visual Studio 2010をインストールした場合、devenvを使うことができます。

    Visual Studio 2010でビルドします:

    groonga-3.0.0> devenv groonga.sln /Build Release

    Visual Studio 2010でインストールします:

    groonga-3.0.0> devenv groonga.sln /Build Release /Project Install

    以上の手順で /reference/executables/groonga が c:\groonga\bin\groonga.exe にインストールされます。

  Mac OS X

このセクションではMac OS X上でgroongaをインストールする方法を説明します。 MacPorts か Homebrew を使ってインストールできます。

32-bit用と64-bit用のパッケージを配布していますが、サーバ用途には64-bitパッケージを利用することをオススメします。32-bit用パッケージはテスト用か開発用にだけ使って下さい。32-bit用パッケージを使った場合は、中程度のサイズのデータでもメモリ不足エラーになることがあります。

  MacPorts

インストール:

% sudo port install groonga

  Homebrew

インストール:

% brew install groonga

  ソースからビルド

Xcode をインストールしてください。

ソースをダウンロードします:

% curl -O http://packages.groonga.org/source/groonga/groonga-3.0.0.tar.gz
% tar xvzf groonga-3.0.0.tar.gz
% cd groonga-3.0.0

configureを実行します（ configure のオプションについては source-configure を参照してください）:

% ./configure

ビルド:

% make -j$(/usr/sbin/sysctl -n hw.ncpu)

インストール:

% sudo make intall

  Debian GNU/Linux

このセクションではDebian GNU/Linux上でgroonga関連のdebパッケージをインストールする方法を説明します。これらのパッケージは apt でインストールできます。

32-bit用と64-bit用のパッケージを配布していますが、サーバ用途には64-bitパッケージを利用することをオススメします。32-bit用パッケージはテスト用か開発用にだけ使って下さい。32-bit用パッケージを使った場合は、中程度のサイズのデータでもメモリ不足エラーになることがあります。

ノート 'groonga'パッケージは全文検索のための最小構成パッケージです。groongaをサーバー用途で使うなら、設定済みの追加パッケージをインストールすることができます。

    サーバー用途のための3つのパッケージがあります。

•   groonga-server-http (簡易HTTPサーバー)

•   groonga-httpd (nginxを元にしたHTTPサーバー)

•   groonga-server-gqtp (GQTPサーバー)

    詳細は /server を参照してください。

  squeeze

groongaのaptリポジトリを追加します。

/etc/apt/sources.list.d/groonga.list:

deb http://packages.groonga.org/debian/ squeeze main
deb-src http://packages.groonga.org/debian/ squeeze main

インストール:

% sudo aptitude update
% sudo aptitude -V -D -y --allow-untrusted install groonga-keyring
% sudo aptitude update
% sudo aptitude -V -D -y install groonga

MeCab をトークナイザーとして使いたいときは、groonga-tokenizer-mecabパッケージをインストールしてください。

groonga-tokenizer-mecabパッケージのインストール:

% sudo aptitude -V -D -y install groonga-tokenizer-mecab

Munin プラグインを提供するパッケージもあります。Muninでgroongaの状態をモニターしたい場合は、groonga-munin-pluginsパッケージをインストールしてください。

groonga-munin-pluginsパッケージのインストール:

% sudo aptitude -V -D -y install groonga-munin-plugins

MySQL互換のノーマライザーをgroongaのプラグインとして提供するパッケージがあります。MySQL互換のノーマライザーを使うには groonga-normalizer-mysql パッケージをインストールしてください。

groonga-normalizer-mysqlパッケージのインストール:

% sudo aptitude -V -D -y install groonga-normalizer-mysql

  wheezy

groongaのaptリポジトリを追加します。

/etc/apt/sources.list.d/groonga.list:

deb http://packages.groonga.org/debian/ wheezy main
deb-src http://packages.groonga.org/debian/ wheezy main

インストール:

% sudo apt-get update
% sudo apt-get -y --allow-unauthenticated install groonga-keyring
% sudo apt-get update
% sudo apt-get -y install groonga

MeCab をトークナイザーとして使いたいときは、groonga-tokenizer-mecabパッケージをインストールしてください。

groonga-tokenizer-mecabパッケージのインストール:

% sudo aptitude -V -D -y install groonga-tokenizer-mecab

Munin プラグインを提供するパッケージもあります。Muninでgroongaの状態をモニターしたい場合は、groonga-munin-pluginsパッケージをインストールしてください。

groonga-munin-pluginsパッケージのインストール:

% sudo aptitude -V -D -y install groonga-munin-plugins

MySQL互換のノーマライザーをgroongaのプラグインとして提供するパッケージがあります。MySQL互換のノーマライザーを使うには groonga-normalizer-mysql パッケージをインストールしてください。

groonga-normalizer-mysqlパッケージのインストール:

% sudo aptitude -V -D -y install groonga-normalizer-mysql

  sid

groongaのaptリポジトリを追加します。

/etc/apt/sources.list.d/groonga.list:

deb http://packages.groonga.org/debian/ unstable main
deb-src http://packages.groonga.org/debian/ unstable main

インストール:

% sudo aptitude update
% sudo aptitude -V -D -y --allow-untrusted install groonga-keyring
% sudo aptitude update
% sudo aptitude -V -D -y install groonga

MeCab をトークナイザーとして使いたいときは、groonga-tokenizer-mecabパッケージをインストールしてください。

groonga-tokenizer-mecabパッケージのインストール:

% sudo aptitude -V -D -y install groonga-tokenizer-mecab

Munin プラグインを提供するパッケージもあります。Muninでgroongaの状態をモニターしたい場合は、groonga-munin-pluginsパッケージをインストールしてください。

groonga-munin-pluginsパッケージのインストール:

% sudo aptitude -V -D -y install groonga-munin-plugins

MySQL互換のノーマライザーをgroongaのプラグインとして提供するパッケージがあります。MySQL互換のノーマライザーを使うには groonga-normalizer-mysql パッケージをインストールしてください。

groonga-normalizer-mysqlパッケージのインストール:

% sudo aptitude -V -D -y install groonga-normalizer-mysql

  ソースからビルド

groongaをビルドするために必要なパッケージをインストールします:

% sudo aptitude -V -D -y install wget tar build-essential zlib1g-dev liblzo2-dev libmsgpack-dev libzmq-dev libevent-dev libmecab-dev

ソースをダウンロードします:

% wget http://packages.groonga.org/source/groonga/groonga-3.0.0.tar.gz
% tar xvzf groonga-3.0.0.tar.gz
% cd groonga-3.0.0

configureを実行します（ configure のオプションについては source-configure を参照してください）:

% ./configure

ビルド:

% make -j$(grep '^processor' /proc/cpuinfo | wc -l)

インストール:

% sudo make intall

  Ubuntu

このセクションではUbuntu上でgroonga関連のdebパッケージをインストールする方法を説明します。これらのパッケージは apt でインストールできます。

32-bit用と64-bit用のパッケージを配布していますが、サーバ用途には64-bitパッケージを利用することをオススメします。32-bit用パッケージはテスト用か開発用にだけ使って下さい。32-bit用パッケージを使った場合は、中程度のサイズのデータでもメモリ不足エラーになることがあります。

ノート 'groonga'パッケージは全文検索のための最小構成パッケージです。groongaをサーバー用途で使うなら、設定済みの追加パッケージをインストールすることができます。

    サーバー用途のための3つのパッケージがあります。

•   groonga-server-http (簡易HTTPサーバー)

•   groonga-httpd (nginxを元にしたHTTPサーバー)

•   groonga-server-gqtp (GQTPサーバー)

    詳細は /server を参照してください。

  10.04 LTS Lucid Lynx

ノート groongaをインストールするためにuniverseリポジトリを有効にしてください:

    % sudo cp /etc/apt/sources.list /etc/apt/sources.list.d/universe.list
    % sudo sed -i'' -e 's/main/universe/' /etc/apt/sources.list.d/universe.list

groongaのaptリポジトリを追加します。

/etc/apt/sources.list.d/groonga.list:

deb http://packages.groonga.org/ubuntu/ lucid universe
deb-src http://packages.groonga.org/ubuntu/ lucid universe

インストール:

% sudo apt-get update
% sudo apt-get -y --allow-unauthenticated install groonga-keyring
% sudo apt-get update
% sudo apt-get -y install groonga

MeCab をトークナイザーとして使いたいときは、groonga-tokenizer-mecabパッケージをインストールしてください。

groonga-tokenizer-mecabパッケージのインストール:

% sudo apt-get -y install groonga-tokenizer-mecab

Munin プラグインを提供するパッケージもあります。Muninでgroongaの状態をモニターしたい場合は、groonga-munin-pluginsパッケージをインストールしてください。

groonga-munin-pluginsパッケージのインストール:

% sudo apt-get -y install groonga-munin-plugins

MySQL互換のノーマライザーをgroongaのプラグインとして提供するパッケージがあります。MySQL互換のノーマライザーを使うには groonga-normalizer-mysql パッケージをインストールしてください。

groonga-normalizer-mysqlパッケージのインストール:

% sudo apt-get -y install groonga-normalizer-mysql

  11.10 Oneiric Ocelot

ノート groongaをインストールするためにuniverseリポジトリを有効にしてください:

    % sudo cp /etc/apt/sources.list /etc/apt/sources.list.d/universe.list
    % sudo sed -i'' -e 's/main/universe/' /etc/apt/sources.list.d/universe.list

groongaのaptリポジトリを追加します。

/etc/apt/sources.list.d/groonga.list:

deb http://packages.groonga.org/ubuntu/ oneiric universe
deb-src http://packages.groonga.org/ubuntu/ oneiric universe

インストール:

% sudo apt-get update
% sudo apt-get -y --allow-unauthenticated install groonga-keyring
% sudo apt-get update
% sudo apt-get -y install groonga

MeCab をトークナイザーとして使いたいときは、groonga-tokenizer-mecabパッケージをインストールしてください。

groonga-tokenizer-mecabパッケージのインストール:

% sudo apt-get -y install groonga-tokenizer-mecab

Munin プラグインを提供するパッケージもあります。Muninでgroongaの状態をモニターしたい場合は、groonga-munin-pluginsパッケージをインストールしてください。

groonga-munin-pluginsパッケージのインストール:

% sudo apt-get -y install groonga-munin-plugins

MySQL互換のノーマライザーをgroongaのプラグインとして提供するパッケージがあります。MySQL互換のノーマライザーを使うには groonga-normalizer-mysql パッケージをインストールしてください。

groonga-normalizer-mysqlパッケージのインストール:

% sudo apt-get -y install groonga-normalizer-mysql

  12.04 LTS Precise Pangolin

ノート groongaをインストールするためにuniverseリポジトリを有効にしてください:

    % sudo cp /etc/apt/sources.list /etc/apt/sources.list.d/universe.list
    % sudo sed -i'' -e 's/main/universe/' /etc/apt/sources.list.d/universe.list

groongaのaptリポジトリを追加します。

/etc/apt/sources.list.d/groonga.list:

deb http://packages.groonga.org/ubuntu/ precise universe
deb-src http://packages.groonga.org/ubuntu/ precise universe

インストール:

% sudo apt-get update
% sudo apt-get -y --allow-unauthenticated install groonga-keyring
% sudo apt-get update
% sudo apt-get -y install groonga

MeCab をトークナイザーとして使いたいときは、groonga-tokenizer-mecabパッケージをインストールしてください。

groonga-tokenizer-mecabパッケージのインストール:

% sudo apt-get -y install groonga-tokenizer-mecab

Munin プラグインを提供するパッケージもあります。Muninでgroongaの状態をモニターしたい場合は、groonga-munin-pluginsパッケージをインストールしてください。

groonga-munin-pluginsパッケージのインストール:

% sudo apt-get -y install groonga-munin-plugins

MySQL互換のノーマライザーをgroongaのプラグインとして提供するパッケージがあります。MySQL互換のノーマライザーを使うには groonga-normalizer-mysql パッケージをインストールしてください。

groonga-normalizer-mysqlパッケージのインストール:

% sudo apt-get -y install groonga-normalizer-mysql

  12.10 Quantal Quetzal

ノート groongaをインストールするためにuniverseリポジトリを有効にしてください:

    % sudo cp /etc/apt/sources.list /etc/apt/sources.list.d/universe.list
    % sudo sed -i'' -e 's/main/universe/' /etc/apt/sources.list.d/universe.list

groongaのaptリポジトリを追加します。

/etc/apt/sources.list.d/groonga.list:

deb http://packages.groonga.org/ubuntu/ quantal universe
deb-src http://packages.groonga.org/ubuntu/ quantal universe

インストール:

% sudo apt-get update
% sudo apt-get -y --allow-unauthenticated install groonga-keyring
% sudo apt-get update
% sudo apt-get -y install groonga

MeCab をトークナイザーとして使いたいときは、groonga-tokenizer-mecabパッケージをインストールしてください。

groonga-tokenizer-mecabパッケージのインストール:

% sudo apt-get -y install groonga-tokenizer-mecab

Munin プラグインを提供するパッケージもあります。Muninでgroongaの状態をモニターしたい場合は、groonga-munin-pluginsパッケージをインストールしてください。

groonga-munin-pluginsパッケージのインストール:

% sudo apt-get -y install groonga-munin-plugins

MySQL互換のノーマライザーをgroongaのプラグインとして提供するパッケージがあります。MySQL互換のノーマライザーを使うには groonga-normalizer-mysql パッケージをインストールしてください。

groonga-normalizer-mysqlパッケージのインストール:

% sudo apt-get -y install groonga-normalizer-mysql

  ソースからビルド

groongaをビルドするために必要なパッケージをインストールします:

% sudo apt-get -V -y install wget tar build-essential zlib1g-dev liblzo2-dev libmsgpack-dev libzmq-dev libevent-dev libmecab-dev

ソースをダウンロードします:

% wget http://packages.groonga.org/source/groonga/groonga-3.0.0.tar.gz
% tar xvzf groonga-3.0.0.tar.gz
% cd groonga-3.0.0

configureを実行します（ configure のオプションについては source-configure を参照してください）:

% ./configure

ビルド:

% make -j$(grep '^processor' /proc/cpuinfo | wc -l)

インストール:

% sudo make intall

  CentOS

このセクションではCentOS上でgroonga関連のPRMパッケージをインストールする方法を説明します。これらのパッケージは yum でインストールできます。

32-bit用と64-bit用のパッケージを配布していますが、サーバ用途には64-bitパッケージを利用することをオススメします。32-bit用パッケージはテスト用か開発用にだけ使って下さい。32-bit用パッケージを使った場合は、中程度のサイズのデータでもメモリ不足エラーになることがあります。

ノート 'groonga'パッケージは全文検索のための最小構成パッケージです。groongaをサーバー用途で使うなら、設定済みの追加パッケージをインストールすることができます。

    サーバー用途のための3つのパッケージがあります。

•   groonga-server-http (簡易HTTPサーバー)

•   groonga-httpd (nginxを元にしたHTTPサーバー)

•   groonga-server-gqtp (GQTPサーバー)

    詳細は /server を参照してください。

  CentOS 5

インストール:

% sudo rpm -ivh http://packages.groonga.org/centos/groonga-release-1.1.0-1.noarch.rpm
% sudo yum makecache
% sudo yum install -y groonga

MeCab をトークナイザーとして使いたいときは、groonga-tokenizer-mecabパッケージをインストールしてください。

groonga-tokenizer-mecabパッケージのインストール:

% sudo yum install -y groonga-tokenizer-mecab

それからMeCabの辞書をインストールします。(mecab-ipadicもしくはmecab-jumandic)

IPA辞書をインストールします:

% sudo yum install -y mecab-ipadic

あるいはJuman辞書をインストールします:

% sudo yum install -y mecab-jumandic

Munin プラグインを提供するパッケージもあります。Muninでgroongaの状態をモニターしたい場合は、groonga-munin-pluginsパッケージをインストールしてください。

ノート groonga-munin-pluginsパッケージはmunin-nodeパッケージを必要としますが、munin-nodeパッケージはCentOSの公式リポジトリには含まれていません。munin-nodeパッケージを yum でインストールするために Repoforge (RPMforge) リポジトリか EPEL リポジトリを有効にする必要があります。

    i386環境でRepoforge (RPMforge)リポジトリを有効にする:

    % wget http://pkgs.repoforge.org/rpmforge-release/rpmforge-release-0.5.2-2.el5.rf.i386.rpm
    % sudo rpm -ivh rpmforge-release-0.5.2-2.el5.rf.i386.rpm

    x86_64環境でRepoforge (RPMforge)リポジトリを有効にする:

    % wget http://pkgs.repoforge.org/rpmforge-release/rpmforge-release-0.5.2-2.el5.rf.x86_64.rpm
    % sudo rpm -ivh rpmforge-release-0.5.2-2.el5.rf.x86_64.rpm

    EPELリポジトリを有効にする（環境非依存）:

    % wget http://download.fedoraproject.org/pub/epel/5/i386/epel-release-5-4.noarch.rpm
    % sudo rpm -ivh epel-release-5-4.noarch.rpm

groonga-munin-pluginsパッケージのインストール:

% sudo yum install -y groonga-munin-plugins

MySQL互換のノーマライザーをgroongaのプラグインとして提供するパッケージがあります。MySQL互換のノーマライザーを使うには groonga-normalizer-mysql パッケージをインストールしてください。

groonga-normalizer-mysqlパッケージのインストール:

% sudo yum install -y install groonga-normalizer-mysql

  CentOS 6

インストール:

% sudo rpm -ivh http://packages.groonga.org/centos/groonga-release-1.1.0-1.noarch.rpm
% sudo yum makecache
% sudo yum install -y groonga

MeCab をトークナイザーとして使いたいときは、groonga-tokenizer-mecabパッケージをインストールしてください。

groonga-tokenizer-mecabパッケージのインストール:

% sudo yum install -y groonga-tokenizer-mecab

それからMeCabの辞書をインストールします。(mecab-ipadicもしくはmecab-jumandic)

IPA辞書をインストールします:

% sudo yum install -y mecab-ipadic

あるいはJuman辞書をインストールします:

% sudo yum install -y mecab-jumandic

Munin プラグインを提供するパッケージもあります。Muninでgroongaの状態をモニターしたい場合は、groonga-munin-pluginsパッケージをインストールしてください。

ノート groonga-munin-pluginsパッケージはmunin-nodeパッケージを必要としますが、munin-nodeパッケージはCentOSの公式リポジトリには含まれていません。munin-nodeパッケージを yum でインストールするために EPEL リポジトリを有効にする必要があります。

    EPELリポジトリを有効にする（環境非依存）:

    % sudo rpm -ivh http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm

groonga-munin-pluginsパッケージのインストール:

% sudo yum install -y groonga-munin-plugins

MySQL互換のノーマライザーをgroongaのプラグインとして提供するパッケージがあります。MySQL互換のノーマライザーを使うには groonga-normalizer-mysql パッケージをインストールしてください。

groonga-normalizer-mysqlパッケージのインストール:

% sudo yum install -y install groonga-normalizer-mysql

  ソースからビルド

groongaをビルドするために必要なパッケージをインストールします:

% sudo yum install -y wget tar gcc-c++ make mecab-devel

ソースをダウンロードします:

% wget http://packages.groonga.org/source/groonga/groonga-3.0.0.tar.gz
% tar xvzf groonga-3.0.0.tar.gz
% cd groonga-3.0.0

configureを実行します（ configure のオプションについては source-configure を参照してください）:

% ./configure

ビルド:

% make -j$(grep '^processor' /proc/cpuinfo | wc -l)

インストール:

% sudo make intall

  Fedora

このセクションではFedora上でgroonga関連のRPMパッケージをインストールする方法を説明します。これらのパッケージは yum でインストールできます。

groonga関連のRPMパッケージはFedoraの公式yumリポジトリにもあります。そのため、groongaのyumリポジトリの代わりにFedoraの公式yumリポジトリを使うこともできます。これらのリポジトリの違いはリリース日当日に最新パッケージが提供されるかどうかです。groongaのyumリポジトリの方では当日提供されます。Fedoraの公式yumリポジトリの方は数日後に提供されます。つまり、ほとんど差はないということです。 :-)

32-bit用と64-bit用のパッケージを配布していますが、サーバ用途には64-bitパッケージを利用することをオススメします。32-bit用パッケージはテスト用か開発用にだけ使って下さい。32-bit用パッケージを使った場合は、中程度のサイズのデータでもメモリ不足エラーになることがあります。

ノート 'groonga'パッケージは全文検索のための最小構成パッケージです。groongaをサーバー用途で使うなら、設定済みの追加パッケージをインストールすることができます。

    サーバー用途のための3つのパッケージがあります。

•   groonga-server-http (簡易HTTPサーバー)

•   groonga-httpd (nginxを元にしたHTTPサーバー)

•   groonga-server-gqtp (GQTPサーバー)

    詳細は /server を参照してください。

  Fedora 18

インストール:

% sudo rpm -ivh http://packages.groonga.org/fedora/groonga-release-1.1.0-1.noarch.rpm
% sudo yum update
% sudo yum install -y groonga

MeCab をトークナイザーとして使いたいときは、groonga-tokenizer-mecabパッケージをインストールしてください。

groonga-tokenizer-mecabパッケージのインストール:

% sudo yum install -y groonga-tokenizer-mecab

それからMeCabの辞書をインストールします。(mecab-ipadicもしくはmecab-jumandic)

IPA辞書をインストールします:

% sudo yum install -y mecab-ipadic

あるいはJuman辞書をインストールします:

% sudo yum install -y mecab-jumandic

Munin プラグインを提供するパッケージもあります。Muninでgroongaの状態をモニターしたい場合は、groonga-munin-pluginsパッケージをインストールしてください。

groonga-munin-pluginsパッケージのインストール:

% sudo yum install -y groonga-munin-plugins

MySQL互換のノーマライザーをgroongaのプラグインとして提供するパッケージがあります。MySQL互換のノーマライザーを使うには groonga-normalizer-mysql パッケージをインストールしてください。

groonga-normalizer-mysqlパッケージのインストール:

% sudo yum install -y install groonga-normalizer-mysql

  ソースからビルド

groongaをビルドするために必要なパッケージをインストールします:

% sudo yum install -y wget tar gcc-c++ make mecab-devel libedit-devel

ソースをダウンロードします:

% wget http://packages.groonga.org/source/groonga/groonga-3.0.0.tar.gz
% tar xvzf groonga-3.0.0.tar.gz
% cd groonga-3.0.0

configureを実行します（ configure のオプションについては source-configure を参照してください）:

% ./configure

ビルド:

% make -j$(grep '^processor' /proc/cpuinfo | wc -l)

インストール:

% sudo make intall

  Oracle Solaris

このセクションではOracle Solaris上でgroongaをソースコードからインストールする方法を説明します。

  Oracle Solaris 11

groongaをビルドするために必要なパッケージをインストールします:

% sudo pkg install gnu-tar gcc-45 system/header

ソースをダウンロードします:

% wget http://packages.groonga.org/source/groonga/groonga-3.0.0.tar.gz
% gtar xvzf groonga-3.0.0.tar.gz
% cd groonga-3.0.0

CFLAGS="-m64" CXXFLAGS="-m64" 変数付きでconfigureを実行します。これらの変数は64-bit版をビルドするために必要です。32-bit版をビルドする場合はこれらの変数を指定しないでしてください。 （ configure のオプションについては source-configure を参照してください）:

% ./configure CFLAGS="-m64" CXXFLAGS="-m64"

ビルド:

% make

インストール:

% sudo make install

  その他

このセクションではUNIX系の環境でgroongaをソースコードからインストールする方法を説明します。

/install にある特定環境用のドキュメントに、その環境向けのより詳細な情報があります。特定環境用のドキュメントがある場合は、まずそちらを参照してください。

  依存関係

groongaは特別なライブラリを必要としませんが、いくつかビルドに必要なツールがあります。

  ツール

以下が必要なツールです:

•   wget 、 curl または Web ブラウザ（ソースアーカイブをダウンロードするため）

•   tar と gzip （ソースアーカイブを展開するため）

•   シェル（ dash 、 bash 、 zsh など、どのようなシェルでもたぶん大丈夫）

•   CコンパイラーとC++コンパイラー （ gcc と g++ がサポート対象だが、他のコンパイラーでもたぶん大丈夫）

•   make （GNU makeがサポート対象だが、BSD makeなど他のmakeでもたぶん大丈夫）

    これらを用意してください。

    シェルの代わりに CMake を使うこともできますが、このドキュメントではCMakeを使ってビルドする方法については説明しません。

    以下はあるとよいツールです:

•   pkg-config （ライブラリを検出するため）

•   sudo （ビルドしたgroongaをインストールするため）

    追加のライブラリを使いたい場合はこれらのツールを用意しておかなければいけません。

  ライブラリ

どのライブラリも必須ではありません。以下はオプションとして使えるライブラリです:

•   MeCab （全文検索対象のドキュメントを形態素解析でトークナイズするため）

•   KyTea （全文検索対象のドキュメントを形態素解析でトークナイズするため）

•   ZeroMQ （ /suggest 用）

•   libevent （ /suggest 用）

•   MessagePack （MessagePack出力サポート用および /suggest 用）

•   libedit （ /reference/executables/groonga のコマンドライン編集用）

•   zlib （カラム値の圧縮用）

•   LZO （カラム値の圧縮用）

    これらのライブラリを使いたい場合は、groongaをインストールする前にライブラリをインストールしてください。

  ソースからビルド

groongaはGNUビルドシステムを使っています。以下は一番簡単なビルド手順です:

% wget http://packages.groonga.org/source/groonga/groonga-3.0.0.tar.gz
% tar xvzf groonga-3.0.0.tar.gz
% cd groonga-3.0.0
% ./configure
% make
% sudo make install

上記の手順を実行すると /usr/local/bin/groonga に /reference/executables/groonga がインストールされます。

デフォルトのビルドでもうまく動くでしょうが、 configure のときにgroongaをカスタマイズすることができます。

以下、それぞれの手順の詳細を説明します。

  configure

まず configure を実行します。重要な configure のオプションは以下の通りです:

  --prefix=PATH

インストール先となるディレクトリを指定します。groonga関連のファイルは ${PATH}/ ディレクトリ以下にインストールされます。

デフォルトは /usr/local 。デフォルトの場合は /reference/executables/groonga は /usr/local/bin/groonga にインストールされます。

以下はシステム全体にgroongaをインストールするのではなく、ユーザーが個人で使う目的で ~/local にインストールする例です:

% ./configure --prefix=$HOME/local

  --localstatedir=PATH

ログファイル、PIDファイル、データベースなど頻繁に変更されるファイルを置くディレクトリを指定します。たとえば、ログファイルは ${PATH}/log/groonga.log に置かれます。

デフォルトは /usr/local/var です。

以下は頻繁に変更されるファイルをシステム全体で使う領域である /var に置く例です:

% ./configure --localstatedir=/var

  --with-log-path=PATH

ログファイルのデフォルトのパスを指定します。ログファイルのデフォルトのパスは /reference/executables/groonga の --log-path コマンドラインオプションで変更できます。そのため、このオプションはそんなに重要なビルドオプションではありません。少し便利にするためのオプションです。

デフォルトは /usr/local/var/log/groonga.log です。 /usr/local/var の部分は --localestatedir オプションで変更できます。

以下はログファイルを共有しているNFSディレクトリ /nfs/log/groonga.log に置く例です:

% ./configure --with-log-path=/nfs/log/groonga.log

  --with-default-encoding=ENCODING

デフォルトのエンコーディングを指定します。有効なエンコーディングは euc_jp 、 sjis 、 utf8 、 latin1 、 koi8r 、 none です。

デフォルトは utf-8 です。

以下はデフォルトのエンコーディングとしてShift_JISを使う例です:

% ./configure --with-default-encoding=sjis

  --with-match-escalation-threshold=NUMBER

マッチ演算でエスカレーションをするかどうかのデフォルトの閾値を指定します。この閾値については match-escalation-threshold を参照してください。-1はマッチ演算でエスカレーションしないという意味です。

デフォルトは0です。

以下はデフォルトではマッチエスカレーションをしないという例です:

% ./configure --with-match-escalation-threshold=-1

  --with-zlib

zlibを使ってカラム値を圧縮する機能を有効にします。

デフォルトでは無効です。

以下はzlibを使ってカラム値を圧縮する機能を有効にする例です:

% ./configure --with-zlib

  --with-lzo

LZOを使ってカラム値を圧縮する機能を有効にします。

デフォルトでは無効です。

以下はLZOを使ってカラム値を圧縮する機能を有効にする例です:

% ./configure --with-lzo

  --with-message-pack=MESSAGE_PACK_INSTALL_PREFIX

MessagePackがどこにインストールされているかを指定します。MessagePackを --prefix=/usr という configure オプションでインストールしていない場合は、MessagePackをビルドするときに指定したパスをこのオプションで指定してください。

もし、MessagePackを --prefix=$HOME/local という configure オプションでインストールした場合は、groongaの configure では --with-message-pack=$HOME/local と指定してください。

デフォルトは /usr です。

以下はMessagePackが --prefix=$HOME/local という configure オプションでインストールされている場合の例です:

% ./configure --with-message-pack=$HOME/local

  --with-munin-plugins

groonga用のMuninプラグインをインストールします。プラグインは ${PREFIX}/share/groonga/munin/plugins/ 以下にインストールされます。

デフォルトではプラグインはインストールされません。

以下はgroonga用のMuninプラグインをインストールする例です:

% ./configure --with-munin-plugins

  --with-package-platform=PLATFORM

initスクリプトなどプラットフォーム依存のシステム管理ファイルをインストールします。利用可能なプラットフォームは redhat と fedora です。 redhat はRed HatおよびCentOSなどのRed Hatクローンのディストリビューション用です。 fedora はFedora用です。

デフォルトではシステム管理ファイルはインストールされません。

以下はCentOS用のシステム管理ファイルをインストールする例です:

% ./configure --with-package-platform=redhat

  --help

すべての configure オプションを表示します。

  make

configure が成功したら make でgroongaをビルドします:

% make

マルチコアCPUを使っている場合は -j オプションを使うとより速くmakeを実行できます。もし、4コアのCPUを使っている場合は、 -j4 オプションを使うともっと速くビルドできます:

% make -j4

make で何かエラーが発生した場合は、そのエラーをレポートしてください: /contribution/report

  make install

これでビルドしたgroongaをインストールできます！:

% sudo make install

${PREFIX} への書き込み権限がある場合は sudo を使う必要はありません。例えば、 --prefix=$HOME/local と指定した場合です。この場合は make install を使ってください:

% make install

コミュニティ

groongaに関する情報を共有するための場所がいくつかあります。あなたの参加をお待ちしています！

  メーリングリスト

groongaに関する話題を扱うメーリングリストがあります。

For English speakers
    groonga-talk@lists.sourceforge.net

For Japanese speakers
    groonga-dev@lists.sourceforge.jp

  Twitter

@groonga がgroonga関連情報をツイートしています。

このアカウントをフォローして最新のgroonga関連情報をゲットしてください！

  Facebook

Facebookのgroongaページ ではgroonga関連情報をシェアしています。

このページをいいね！して最新のgroonga関連情報をゲットしてください！

チュートリアル

  基本的な操作

groongaには、Cのライブラリとして使用する方法と、groonga実行ファイルを通して使用する方法があります。本チュートリアルでは、groonga実行ファイルを使用する方法について説明します。groonga実行ファイルを使って、データベースの作成・操作・サーバの起動・サーバへの接続などの操作が行えます。

  データベースの作成

groongaユーザへの第一歩はデータベースの作成です。まずは以下の書式をご覧ください。

書式:

groonga -n DB_PATH

-n オプションは、データベースの作成を指示します。DB_PATHは、新しく作成するデータベースのパスを指定します。データベースは複数のファイルによって構成されるため、正確には、データベースの入り口となるファイルのパスとして使用されます。また、データベースを構成する他のファイルについては、DB_PATHがパスのプレフィックスとして使用されます。指定されたパスにファイルが存在しているときは失敗するので注意してください。

上記のコマンドは、データベースを作成してから、コマンドの入力を受け付ける対話モードに入ります。Ctrlキーを押しながらdキーを押すと、対話モードから抜けることができます。

実行例:

% groonga -n /tmp/groonga-databases/introduction.db

データベースを作成に成功すれば、/tmp/groonga-databases以下にデータベースを構成するファイルが配置されます。

  データベースの操作

以下の書式は、既存のデータベースを操作する方法を示しています。

書式:

groonga DB_PATH [COMMAND]

DB_PATHには操作対象のデータベースを指定します。指定したデータベースが存在しないときは失敗します。

COMMAND が指定された場合、COMMAND を実行した後、実行結果を返します。指定されなかった場合には、対話モードに入ります。対話モードでは、標準入力からコマンドを読み込み、順次実行します。本チュートリアルでは、対話モードを主に使用します。

それでは、 /reference/commands/status コマンドを実行して、groongaの実行状態を確認してみましょう。

実行例:

% groonga /tmp/groonga-databases/introduction.db
status
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   {
#     "uptime": 0,
#     "max_command_version": 2,
#     "n_queries": 0,
#     "cache_hit_rate": 0.0,
#     "version": "2.1.0",
#     "alloc_count": 152,
#     "command_version": 1,
#     "starttime": 1356678603,
#     "default_command_version": 1
#   }
# ]

以上のように、コマンドの実行結果は基本的にjson形式の配列として返却されます。配列の先頭には、エラーコードや実行時間などの情報が入ります。2番目の要素には、指示された操作の実行結果が入ります。

  コマンドの書式

データベースを操作するコマンドには、以下の書式で引数を与えます。:

Form_1: COMMAND VALUE_1 VALUE_2 ..
Form_2: COMMAND --NAME_1 VALUE_1 --NAME_2 VALUE_2 ..

書式1では値を適切な順番で渡す必要があります。このような引数は、位置によって値の意味が決まるため、位置固定引数などと呼ばれることもあります。

書式2では値を名前と一緒に渡します。そのため、任意の順序で引数を指定することができます。このような引数は、名前付き引数やキーワード引数と呼ばれることもあります。

空白や特殊な記号（ダブルクォート、シングルクォート、および丸括弧）を含む値を指定したいときは、シングルクォート(')かダブルクォート(")で値を囲むようにしてください。

詳しくは、 /reference/executables/groonga のコマンドの項を参考にしてください。

  主なコマンド

/reference/commands/status
    groongaプロセスの状態を表示します。

/reference/commands/table_list
    データベースに定義されているテーブルのリストを表示します。

/reference/commands/column_list
    テーブルに定義されているカラムのリストを表示します。

/reference/commands/table_create
    データベースにテーブルを追加します。

/reference/commands/column_create
    テーブルにカラムを追加します。

/reference/commands/select
    テーブルに含まれるレコードを検索して表示します。

/reference/commands/load
    テーブルにレコードを挿入します。

  テーブルの作成

/reference/commands/table_create コマンドを使用してテーブルを作成します。

groongaのテーブルには基本的に主キーが必要であり、テーブルを作成する際には型と格納方法も併せて指定する必要があります。

型には数値や文字列などがあります。ここではデータの種類を表しているものという程度に考えてください。詳細は /reference/types に記述されています。主キーの格納方法は、主キーを条件とする検索にかかる時間や、前方一致検索の可否などを左右します。こちらも後で説明します。

それでは、テーブルを作成してみましょう。以下の例では、主キーのあるテーブルを作成します。 name 引数はテーブルの引数を指定します。 flags 引数は主キーの格納方法を指定するために使っています。 key_type 引数は主キーの型を指定します。

実行例:

table_create --name Site --flags TABLE_HASH_KEY --key_type ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]

実行結果の第2要素は、操作が成功したことを示しています。

  テーブルの表示

/reference/commands/select コマンドを用いて、テーブルの中身を表示することができます。

実行例:

select --table Site
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         0
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ]
#       ]
#     ]
#   ]
# ]

/reference/commands/select にテーブル名のみを指定すると、指定したテーブルの中身を10件まで表示します。実行結果の[0]はテーブルに含まれるレコードの数を示しています。今回は何も登録されていないため0件です。レコード数の次に表示されている配列はテーブルの構成を示しています。["_id","Uint32"]はUInt32型の値を持つ_idという名前のカラム、["_key","ShortText"]はShortText型の値を持つ_keyという名前のカラムをそれぞれ表しています。

上記の_idカラムと_keyカラムの2つのカラムは必須のカラムです。_idカラムはgroongaが自動的に割り当てるIDを格納します。_keyカラムは主キーを格納します。これらのカラム名を変更することはできません。

  カラムの作成

/reference/commands/column_create コマンドを用いて、カラムを作成することができます。

それでは、カラムを作成してみましょう。以下の例では、新しいカラムをSiteテーブルに追加します。 table 引数はテーブルの名前を指定します。 name 引数は新しいカラムの名前を指定します。 type 引数はカラムに格納する値の型を指定します。

実行例:

column_create --table Site --name title --type ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
select --table Site
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         0
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "title",
#           "ShortText"
#         ]
#       ]
#     ]
#   ]
# ]

  データのロード

/reference/commands/load コマンドは、JSON形式のレコードを受け取り、テーブルに格納します。

以下の例では9つのレコードをSiteテーブルに格納します。

実行例:

load --table Site
[
{"_key":"http://example.org/","title":"This is test record 1!"},
{"_key":"http://example.net/","title":"test record 2."},
{"_key":"http://example.com/","title":"test test record three."},
{"_key":"http://example.net/afr","title":"test record four."},
{"_key":"http://example.org/aba","title":"test test test record five."},
{"_key":"http://example.com/rab","title":"test test test test record six."},
{"_key":"http://example.net/atv","title":"test test test record seven."},
{"_key":"http://example.org/gat","title":"test test record eight."},
{"_key":"http://example.com/vdw","title":"test test record nine."},
]
# [[0, 1337566253.89858, 0.000355720520019531], 9]

実行結果の第2要素はロードされたレコードの数を示しています。上記の操作では、すべてのレコードを問題なくロードできています。

念のため、データが入っていることを確認してみましょう。

実行例:

select --table Site
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         9
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "title",
#           "ShortText"
#         ]
#       ],
#       [
#         1,
#         "http://example.org/",
#         "This is test record 1!"
#       ],
#       [
#         2,
#         "http://example.net/",
#         "test record 2."
#       ],
#       [
#         3,
#         "http://example.com/",
#         "test test record three."
#       ],
#       [
#         4,
#         "http://example.net/afr",
#         "test record four."
#       ],
#       [
#         5,
#         "http://example.org/aba",
#         "test test test record five."
#       ],
#       [
#         6,
#         "http://example.com/rab",
#         "test test test test record six."
#       ],
#       [
#         7,
#         "http://example.net/atv",
#         "test test test record seven."
#       ],
#       [
#         8,
#         "http://example.org/gat",
#         "test test record eight."
#       ],
#       [
#         9,
#         "http://example.com/vdw",
#         "test test record nine."
#       ]
#     ]
#   ]
# ]

  レコードの取得

/reference/commands/select コマンドを用いて、テーブルの中身を表示することができます。

query 引数を使って検索条件が指定された場合、 /reference/commands/select コマンドは検索条件に適合するレコードを検索し、検索結果を出力します。

それでは、IDを指定してレコードを取り出してみましょう。以下の例では、Siteテーブルの先頭レコードを取り出します。正確には、 query 引数を使って _id カラムに1が格納されているレコードを要求しています。

実行例:

select --table Site --query _id:1
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "title",
#           "ShortText"
#         ]
#       ],
#       [
#         1,
#         "http://example.org/",
#         "This is test record 1!"
#       ]
#     ]
#   ]
# ]

次に、主キーを指定してレコードを取り出してみましょう。以下の例では、主キーが "http://example.org/" のキーを取り出します。正確には、 query 引数を使って _key カラムに "http://example.org/" が格納されているレコードを要求しています。

実行例:

select --table Site --query '_key:"http://example.org/"'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "title",
#           "ShortText"
#         ]
#       ],
#       [
#         1,
#         "http://example.org/",
#         "This is test record 1!"
#       ]
#     ]
#   ]
# ]

  全文検索用の語彙表の作成

そろそろ全文検索の使い方について見ていきましょう。

groongaでは転置インデックスを使って高速な全文検索を実現しています。そのため、まずは転置インデックスとして用いるテーブルを作成する必要があります。テーブルの内容は、文書に含まれる単語やN-gramなどの索引語を主キーとして、各カラムに索引語の位置情報を格納するという構成になります。結果として、主キーのカラムは全文検索における語彙表の役割を果たします。

以下の例では、Termsという名前のテーブルを転置インデックスの語彙表として作成しています。索引語を格納するため、主キーの型はShortTextです。

実行例:

table_create --name Terms --flags TABLE_PAT_KEY|KEY_NORMALIZE --key_type ShortText --default_tokenizer TokenBigram
# [[0, 1337566253.89858, 0.000355720520019531], true]

/reference/commands/table_create には多くの引数が指定されているものの、本チュートリアルではすべてを理解する必要はありません。以下に簡単な説明を述べますが、読み飛ばしてもらってかまいません。

TABLE_PAT_KEYフラグは、主キーをパトリシア木に格納することを指示しています。KEY_NORMALIZEフラグは、索引語を正規化して登録することを指示しています。 default_tokenizer 引数には、検索対象の文書をトークナイズする方式を指定するようになっています。上記の例では、一般的にN-gramと呼ばれるインデックス方式に対応するTokenBigramを指定しています。

  全文検索用のインデックスカラムの作成

次に必要なのは、インデックス型のカラムを作成することです。このカラムは、関連付けられたカラムに対する全文検索に利用されます。つまり、全文検索を行いたいカラムに対してインデックスを作成することに相当します。

それでは、インデックスカラムを作成してみましょう。以下の例では、Siteテーブルのカラムに対するインデックスカラムを作成します。それでは、Siteテーブルのtitleカラムを全文検索の対象とするべく、インデックス型のカラムを作成してみましょう。

実行例:

column_create --table Terms --name blog_title --flags COLUMN_INDEX|WITH_POSITION --type Site --source title
# [[0, 1337566253.89858, 0.000355720520019531], true]

table 引数は語彙表を指定し、 name 引数はインデックスカラムを指定します。また、 type 引数はインデックスの対象となるテーブルを指定し、 source 引数はインデックスの対象となるカラムを指定します。COLUMN_INDEXフラグはインデックスカラムの作成を指示し、WITH_POSITIONフラグは各索引語の位置情報をインデックスに含めることを指示します。一般的な全文検索インデックスを作成したいときは、COLUMN_INDEX|WITH_POSITIONを指定してください。索引語の位置情報については、本チュートリアルでは触れません。

ノート 語彙表とインデックスカラムを作成するタイミングは、データをロードする前後のどちらでも問題ありません。データをロードした後でインデックスを作成し、さらに新しいデータをロードすることもできます。インデックスの作成を指示したタイミングでレコードが既に存在するときは、静的にインデックスを作成します。一方、インデックスを作成した後で追加されたレコードについては、動的にインデックスを更新します。

  全文検索

インデックスを作成したことにより、 /reference/commands/select コマンドによる全文検索が可能になります。

全文検索のクエリは query 引数により指定することができます。以下の例では、titleカラムに "this" という文字列が含まれているレコードを検索します。 query 引数に含まれる '@' は、全文検索を指示しています。語彙表の作成において KEY_NORMALIZE フラグを指定したときは、全角・半角や大文字・小文字などの違いが吸収されることに注意してください。

実行例:

select --table Site --query title:@this
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "title",
#           "ShortText"
#         ]
#       ],
#       [
#         1,
#         "http://example.org/",
#         "This is test record 1!"
#       ]
#     ]
#   ]
# ]

上記の例では、"This" という単語を含む先頭レコードのみが検索条件に適合します。

/reference/commands/select コマンドには、 match_columns という引数が存在します。このパラメータはデフォルトで検索対象にするカラムを指定するもので、カラム名を指定しない検索条件にのみ適用されます。 [1]

"--match_columns title" と "--query this" の組み合わせを指定すると、 "--query title:@this" を指定したときと同じ検索条件になります。

実行例:

select --table Site --match_columns title --query this
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "title",
#           "ShortText"
#         ]
#       ],
#       [
#         1,
#         "http://example.org/",
#         "This is test record 1!"
#       ]
#     ]
#   ]
# ]

  出力カラムの指定

/reference/commands/select コマンドにおいて output_columns 引数を用いることで、検索結果に含めるカラムを指定することができます。複数のカラムを指定するときは、カンマ（,）区切りでカラムを列挙します。

実行例:

select --table Site --output_columns _key,title,_score --query title:@test
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         9
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "title",
#           "ShortText"
#         ],
#         [
#           "_score",
#           "Int32"
#         ]
#       ],
#       [
#         "http://example.org/",
#         "This is test record 1!",
#         1
#       ],
#       [
#         "http://example.net/",
#         "test record 2.",
#         1
#       ],
#       [
#         "http://example.com/",
#         "test test record three.",
#         2
#       ],
#       [
#         "http://example.net/afr",
#         "test record four.",
#         1
#       ],
#       [
#         "http://example.org/aba",
#         "test test test record five.",
#         3
#       ],
#       [
#         "http://example.com/rab",
#         "test test test test record six.",
#         4
#       ],
#       [
#         "http://example.net/atv",
#         "test test test record seven.",
#         3
#       ],
#       [
#         "http://example.org/gat",
#         "test test record eight.",
#         2
#       ],
#       [
#         "http://example.com/vdw",
#         "test test record nine.",
#         2
#       ]
#     ]
#   ]
# ]

上記の例では、_scoreカラムを含む3つのカラムを指定しています。_scoreカラムはgroongaの検索結果に含まれるカラムであり、全文検索の条件に合致するレコードほど高い数値が入ります。

  表示範囲指定

/reference/commands/select コマンドにおいて offset 引数と limit 引数を用いることで、検索結果の一部のみを表示することができます。大量の検索結果を分割してページ単位で表示したい場合などに有用です。

offset 引数には、検索結果における始点を指定します。検索結果の1件目が必要な場合、 offset 引数を省略するか、0を指定するようにしてください。 limit 引数には、検索結果の表示件数を指定します。

実行例:

select --table Site --offset 0 --limit 3
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         9
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "title",
#           "ShortText"
#         ]
#       ],
#       [
#         1,
#         "http://example.org/",
#         "This is test record 1!"
#       ],
#       [
#         2,
#         "http://example.net/",
#         "test record 2."
#       ],
#       [
#         3,
#         "http://example.com/",
#         "test test record three."
#       ]
#     ]
#   ]
# ]
select --table Site --offset 3 --limit 3
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         9
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "title",
#           "ShortText"
#         ]
#       ],
#       [
#         4,
#         "http://example.net/afr",
#         "test record four."
#       ],
#       [
#         5,
#         "http://example.org/aba",
#         "test test test record five."
#       ],
#       [
#         6,
#         "http://example.com/rab",
#         "test test test test record six."
#       ]
#     ]
#   ]
# ]
select --table Site --offset 7 --limit 3
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         9
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "title",
#           "ShortText"
#         ]
#       ],
#       [
#         8,
#         "http://example.org/gat",
#         "test test record eight."
#       ],
#       [
#         9,
#         "http://example.com/vdw",
#         "test test record nine."
#       ]
#     ]
#   ]
# ]

  検索結果の並べ替え

/reference/commands/select コマンドに sortby 引数を渡すことにより、検索結果を並べ替えることができます。

sortby 引数には、整列の基準として用いるカラムを指定します。検索結果は指定したカラムの値が昇順になるように並べ替えられます。 sortby 引数の中でカラム名の前にハイフン（-）を付けることにより、降順に並べ替えることもできます。

以下の例では、Siteテーブルのレコードを逆順に表示しています。

実行例:

select --table Site --sortby -_id
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         9
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "title",
#           "ShortText"
#         ]
#       ],
#       [
#         9,
#         "http://example.com/vdw",
#         "test test record nine."
#       ],
#       [
#         8,
#         "http://example.org/gat",
#         "test test record eight."
#       ],
#       [
#         7,
#         "http://example.net/atv",
#         "test test test record seven."
#       ],
#       [
#         6,
#         "http://example.com/rab",
#         "test test test test record six."
#       ],
#       [
#         5,
#         "http://example.org/aba",
#         "test test test record five."
#       ],
#       [
#         4,
#         "http://example.net/afr",
#         "test record four."
#       ],
#       [
#         3,
#         "http://example.com/",
#         "test test record three."
#       ],
#       [
#         2,
#         "http://example.net/",
#         "test record 2."
#       ],
#       [
#         1,
#         "http://example.org/",
#         "This is test record 1!"
#       ]
#     ]
#   ]
# ]

次の例では、_scoreカラムを整列の基準とすることにより、検索結果のランキングをおこなっています。検索結果はクエリとの関連性が高い順に並べ替えられます。

実行例:

select --table Site --query title:@test --output_columns _id,_score,title --sortby -_score
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         9
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_score",
#           "Int32"
#         ],
#         [
#           "title",
#           "ShortText"
#         ]
#       ],
#       [
#         6,
#         4,
#         "test test test test record six."
#       ],
#       [
#         5,
#         3,
#         "test test test record five."
#       ],
#       [
#         7,
#         3,
#         "test test test record seven."
#       ],
#       [
#         8,
#         2,
#         "test test record eight."
#       ],
#       [
#         3,
#         2,
#         "test test record three."
#       ],
#       [
#         9,
#         2,
#         "test test record nine."
#       ],
#       [
#         1,
#         1,
#         "This is test record 1!"
#       ],
#       [
#         4,
#         1,
#         "test record four."
#       ],
#       [
#         2,
#         1,
#         "test record 2."
#       ]
#     ]
#   ]
# ]

整列の基準となるカラムを複数指定したいときは、カンマ（,）区切りでカラムを列挙します。複数のカラムを指定したときは、最初のカラムを基準として整列した後、最初のカラムに同じ値が格納されているレコードを次のカラムを基準として整列します。

実行例:

select --table Site --query title:@test --output_columns _id,_score,title --sortby -_score,_id
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         9
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_score",
#           "Int32"
#         ],
#         [
#           "title",
#           "ShortText"
#         ]
#       ],
#       [
#         6,
#         4,
#         "test test test test record six."
#       ],
#       [
#         5,
#         3,
#         "test test test record five."
#       ],
#       [
#         7,
#         3,
#         "test test test record seven."
#       ],
#       [
#         3,
#         2,
#         "test test record three."
#       ],
#       [
#         8,
#         2,
#         "test test record eight."
#       ],
#       [
#         9,
#         2,
#         "test test record nine."
#       ],
#       [
#         1,
#         1,
#         "This is test record 1!"
#       ],
#       [
#         2,
#         1,
#         "test record 2."
#       ],
#       [
#         4,
#         1,
#         "test record four."
#       ]
#     ]
#   ]
# ]
脚注

[1] 現在のバージョンでは、全文検索インデックスが存在する場合にのみ、 match_columns 引数を利用することができます。通常のカラムでの絞り込みには利用できません。

  リモートアクセス

groongaをサーバとして起動することにより、ネットワークを介してデータベースにアクセスできるようになります。groongaがサポートしているプロトコルは、groongaの専用プロトコルであるgqtp、memcachedバイナリプロトコル、HTTPの三種類です。

  groonga専用プロトコル（gqtp）

  gqtpサーバの起動

groongaには、専用のプロトコルであるgqtpが存在します。gqtpを用いることにより、データベースへとリモートアクセスすることができます。以下の書式はgqtpサーバの起動方法を示しています。

書式:

groonga [-p PORT_NUMBER] -s DB_PATH

-s オプションはgroongaをサーバとして起動するためのオプションです。DB_PATHには既存のデータベースのパスを指定します。 -p オプションとその引数により、サーバのポート番号を指定することができます。ポート番号を省略した場合は10041が使用されます。

以下のコマンドにより、デフォルトのポート番号で待ち受けるサーバを起動することができます。サーバは指定されたデータベースへの操作を受け付けます。

実行例:

% groonga -s /tmp/groonga-databases/introduction.db
Ctrl-c
%

  gqtpデーモンの起動

gqtpサーバはデーモンとして起動することができます。オプションとして、 -s の代わりに -d を与えてください。

書式:

groonga [-p PORT_NUMBER] -d DB_PATH

groongaをデーモンとして起動したときは、デーモンのプロセスIDが表示されます。以下の例では、12345というプロセスIDが表示されています。サーバとして起動した場合と同様に、指定されたデータベースへの操作を受け付けます。

実行例:

% groonga -d /tmp/groonga-databases/introduction.db
12345
%

  gqtpサーバへの接続

gqtpサーバに接続するクライアントは、以下のように起動します。

書式:

groonga [-p PORT_NUMBER] -c [HOST_NAME_OR_IP_ADDRESS]

上記のコマンドによって起動されたクライアントは、サーバとの接続に成功すると対話モードに入ります。HOST_NAME_OR_IP_ADDRESSにはサーバのホスト名もしくはIPアドレスを指定します。HOST_NAME_OR_IP_ADDRESSが省略されたときは"localhost"をサーバのホスト名として採用します。また、 -p オプションとその引数により、サーバのポート番号を指定することができます。ポート番号を省略した場合は10041が使用されます。

実行例:

% groonga -c
status
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   {
#     "uptime": 0,
#     "max_command_version": 2,
#     "n_queries": 0,
#     "cache_hit_rate": 0.0,
#     "version": "2.0.5",
#     "alloc_count": 121,
#     "command_version": 1,
#     "starttime": 1343713541,
#     "default_command_version": 1
#   }
# ]
> ctrl-d
%

対話モードでは、標準入力からコマンドを読み込んで順次実行します。

  gqtpサーバの終了

gqtpサーバを終了する安全は方法は、クライアントを起動して /reference/commands/shutdown を発行することです。

実行例:

% groonga -c
> shutdown
%

  memcachedバイナリプロトコル

groongaはmemcachedバイナリプロトコルをサポートしています。以下の書式はmemcachedバイナリプロトコルのサーバをデーモンとして起動する方法を示しています。

書式:

groonga [-p PORT_NUMBER] -d --protocol memcached DB_PATH

--protocol オプションとその引数により、サーバのプロトコルを指定することができます。"memcached"はmemcachedバイナリプロトコルを示しています。

  HTTP

  HTTPサーバの起動

groongaはHTTPをサポートしています。以下の書式はHTTPサーバをデーモンとして起動する方法を示しています。

書式:

groonga [-p PORT_NUMBER] -d --protocol http DB_PATH

--protocol オプションとその引数により、サーバのプロトコルを指定することができます。"http"はHTTPサーバの起動を指示しています。

以下のコマンドは、ポート番号80で待ち受けるHTTPサーバをデーモンとして起動します。

実行例:

% groonga -p 80 -d --protocol http /tmp/groonga-databases/introduction.db
%

  HTTPサーバへのコマンド送信

groongaがHTTPサーバとして起動されているときは、/d/COMMAND_NAME というURLにアクセスすることにより、コマンドを実行することができます。コマンドの引数は、HTTPのGETパラメータとして渡します。引数の書式は "?NAME_1=VALUE_1&NAME_2=VALUE_2&..." となります。

以下の例は、HTTPサーバに対するコマンドの送り方を示しています。

実行例:

http://HOST_NAME_OR_IP_ADDRESS[:PORT_NUMBER]/d/status
Executed command:
status
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   {
#     "uptime": 0,
#     "max_command_version": 2,
#     "n_queries": 0,
#     "cache_hit_rate": 0.0,
#     "version": "2.0.5",
#     "alloc_count": 122,
#     "command_version": 1,
#     "starttime": 1343713541,
#     "default_command_version": 1
#   }
# ]
http://HOST_NAME_OR_IP_ADDRESS[:PORT_NUMBER]/d/select?table=Site&query=title:@this
Executed command:
select --table Site --query title:@this
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "country",
#           "SiteCountry"
#         ],
#         [
#           "domain",
#           "SiteDomain"
#         ],
#         [
#           "link",
#           "Site"
#         ],
#         [
#           "links",
#           "Site"
#         ],
#         [
#           "location",
#           "WGS84GeoPoint"
#         ],
#         [
#           "title",
#           "ShortText"
#         ]
#       ],
#       [
#         1,
#         "http://example.org/",
#         "japan",
#         ".org",
#         "http://example.net/",
#         [
#           "http://example.net/",
#           "http://example.org/",
#           "http://example.com/"
#         ],
#         "128452975x503157902",
#         "This is test record 1!"
#       ]
#     ]
#   ]
# ]

  ブラウザベースの管理ツール

groongaをHTTPサーバとして起動しているときは、ブラウザベースの管理ツールを使うことにより、データベースを簡単に管理することができます。管理ツールを使いたいときは、ブラウザを使って http://HOST_NAME_OR_IP_ADDRESS[:PORT_NUMBER]/ へとアクセスしてください。管理ツールの使用には、JavaScriptの実行が有効になっている必要があります。

  セキュリティ

groongaのサーバには認証機能がありません。誰でもデータベースの内容を閲覧・修正することができます。iptablesなどを用いてアクセス元IPアドレスを制限することを推奨します。

  いろいろなデータの保存

groongaは全文検索エンジンを起源として独自のカラムストアを持つに至るわけですが、索引語や文書を保存するだけでなく、数値や文字列、日時や経緯度など、いろいろなデータを保存することができます。本チュートリアルでは、groongaで保存できるデータの種類、およびに保存の方法を説明します。

  データの種類

groongaにおいて利用できる基本型は、真偽値、数値、文字列、日時、経緯度の5種類に大別できます。基本型において、数値は整数・浮動小数点数の違い、符号の有無と割り当てるビット数によって細分化できるほか、文字列は長さの上限によって細分化できます。また、経緯度には測地系による分類があります。詳しくは /reference/types を参照してください。

拡張型としては、別テーブルを参照するための情報であるテーブル参照を保存することができます。また、基本型もしくはテーブル参照を複数まとめて保存できるように、ベクターカラムをサポートしています。

それでは、本チュートリアルで使用するテーブルを作成しておきましょう。

実行例:

table_create --name ToyBox --flags TABLE_HASH_KEY --key_type ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]

  真偽値

ブール型は真偽値（true/false）を表現するための型です。ブール型のカラムを作成するには、 /reference/commands/column_create コマンドの type 引数に Bool を指定します。ブール型のデフォルト値はfalseです。

以下の例では、ブール型のカラムを作成し、3つのレコードを追加します。3番目のレコードについては、値を省略しているため、デフォルト値が格納されます。

実行例:

column_create --table ToyBox --name is_animal --type Bool
# [[0, 1337566253.89858, 0.000355720520019531], true]
load --table ToyBox
[
{"_key":"Monkey","is_animal":true}
{"_key":"Flower","is_animal":false}
{"_key":"Block"}
]
# [[0, 1337566253.89858, 0.000355720520019531], 3]
select --table ToyBox --output_columns _key,is_animal
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         3
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "is_animal",
#           "Bool"
#         ]
#       ],
#       [
#         "Monkey",
#         true
#       ],
#       [
#         "Flower",
#         false
#       ],
#       [
#         "Block",
#         false
#       ]
#     ]
#   ]
# ]

  数値

数値型は、整数と浮動小数点数に分けることができます。整数は、符号付き整数と符号なし整数に分けることができるだけでなく、割り当てるビット数によっても分けることができます。割り当てるビット数を大きくすると、カラムのサイズは大きくなってしまいますが、表現できる整数の範囲を大きくすることができます。詳しくは /reference/types を参照してください。数値型のデフォルト値はいずれも0です。

以下の例では、Int8型のカラムとFloat型のカラムを作成し、既存のレコードを更新します。weightカラムについては、指定した値が問題なく格納されています。一方、priceカラムに指定した小数については、小数点以下を切り捨てた値が格納されています。また、表現できる範囲を超える値を格納しようとした2番目のレコードについては、指定した値とは異なる値が格納されています。このように、表現できる範囲を超える値を指定すると、操作後の値は未定義になるので注意してください。

実行例:

column_create --table ToyBox --name price --type Int8
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create --table ToyBox --name weight --type Float
# [[0, 1337566253.89858, 0.000355720520019531], true]
load --table ToyBox
[
{"_key":"Monkey","price":15.9}
{"_key":"Flower","price":200,"weight":0.13}
{"_key":"Block","weight":25.7}
]
# [[0, 1337566253.89858, 0.000355720520019531], 3]
select --table ToyBox --output_columns _key,price,weight
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         3
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "price",
#           "Int8"
#         ],
#         [
#           "weight",
#           "Float"
#         ]
#       ],
#       [
#         "Monkey",
#         15,
#         0.0
#       ],
#       [
#         "Flower",
#         -56,
#         0.13
#       ],
#       [
#         "Block",
#         0,
#         25.7
#       ]
#     ]
#   ]
# ]

  文字列

文字列型は、長さの上限によって分けることができます。詳しくは /reference/types を参照してください。文字列型のデフォルト値は長さ0の文字列です。

以下の例では、ShortText型のカラムを作成し、IDが1と2のレコードを更新します。更新しないレコードについては、デフォルト値のままとなります。

実行例:

column_create --table ToyBox --name name --type ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
load --table ToyBox
[
{"_key":"Monkey","name":"Grease"}
{"_key":"Flower","name":"Rose"}
]
# [[0, 1337566253.89858, 0.000355720520019531], 2]
select --table ToyBox --output_columns _key,name
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         3
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "name",
#           "ShortText"
#         ]
#       ],
#       [
#         "Monkey",
#         "Grease"
#       ],
#       [
#         "Flower",
#         "Rose"
#       ],
#       [
#         "Block",
#         ""
#       ]
#     ]
#   ]
# ]

  日時

日時を表現するための型はTimeです。内部では1970年1月1日0時0分0秒を基準とする経過時間をマイクロ秒単位で表現します。符号付きの整数を用いるため、1970年以前の日時も表現することができます。内部表現はマイクロ秒単位の整数ですが、 /reference/commands/load コマンドおよび /reference/commands/select コマンドでは、経過秒数による指定・表示となります。デフォルト値は1970年1月1日0時0分0秒のことを表す0.0です。

以下の例では、Time型のカラムを作成し、IDが2と3のレコードを更新します。更新しないレコードについては、デフォルト値のままとなります。

実行例:

column_create --table ToyBox --name time --type Time
# [[0, 1337566253.89858, 0.000355720520019531], true]
load --table ToyBox
[
{"_key":"Flower","time":1234567890.1234569999}
{"_key":"Block","time":-1234567890}
]
# [[0, 1337566253.89858, 0.000355720520019531], 2]
select --table ToyBox --output_columns _key,time
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         3
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "time",
#           "Time"
#         ]
#       ],
#       [
#         "Monkey",
#         0.0
#       ],
#       [
#         "Flower",
#         1234567890.12346
#       ],
#       [
#         "Block",
#         -1234567890.0
#       ]
#     ]
#   ]
# ]

  経緯度

経緯度を表現するための型は、測地系によって分けることができます。詳しくは /reference/types を参照してください。経緯度の指定・表示には、以下に示す形式の文字列を使います。

•   "経度のミリ秒表記x緯度のミリ秒表記" （例: "128452975x503157902"）

•   "経度の度数表記x緯度の度数表記" （例: "35.6813819x139.7660839"）

    小数点を含んでいなければミリ秒表記、小数点を含んでいれば度数表記として扱われます。ミリ秒表記と度数表記を混ぜたときの動作は未定義なので注意してください。経度と緯度の区切りとしては、'x' のほかに ',' を使うことができます。経緯度のデフォルト値は "0x0" です。

    以下の例では、世界測地系を用いるWGS84GeoPoint型のカラムを作成し、IDが1と3のレコードを更新します。更新しないレコードについては、デフォルト値のままとなります。

    実行例:

    column_create --table ToyBox --name location --type WGS84GeoPoint
    # [[0, 1337566253.89858, 0.000355720520019531], true]
    load --table ToyBox
    [
    {"_key":"Monkey","location":"128452975x503157902"}
    {"_key":"Block","location":"35.6813819x139.7660839"}
    ]
    # [[0, 1337566253.89858, 0.000355720520019531], 2]
    select --table ToyBox --output_columns _key,location
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         3
    #       ],
    #       [
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "location",
    #           "WGS84GeoPoint"
    #         ]
    #       ],
    #       [
    #         "Monkey",
    #         "128452975x503157902"
    #       ],
    #       [
    #         "Flower",
    #         "0x0"
    #       ],
    #       [
    #         "Block",
    #         "128452975x503157902"
    #       ]
    #     ]
    #   ]
    # ]

  テーブル参照

groongaでは、テーブル参照のカラム、すなわち関連付けたテーブルを参照するカラムを作成できます。より正確には、カラム作成時に参照先となるテーブルとの関連付けをおこない、参照先テーブルにおけるレコードIDを格納しておくことにより、参照先のレコードにアクセスできるようにします。

テーブル参照のカラムがあるときは、 reference/commands/select コマンドの output_columns 引数に "参照元カラム.参照先カラム" と指定することにより、参照先カラムの値を取り出すことができます。参照元カラムのみを指定したときは、 "参照元カラム名._key" と同様の扱いとなり、参照先レコードの主キーが取り出されます。テーブル参照が有効なレコードを指していないときは、参照先カラムのデフォルト値が取り出されるようになっています。

ここでは、先のチュートリアルで作成したSiteテーブルにlinkという新たなカラムを作成し、サイト間のリンク関係を保存できるようにしてみましょう。

実行例:

column_create --table Site --name link --type Site
# [[0, 1337566253.89858, 0.000355720520019531], true]
load --table Site
[{"_key":"http://example.org/","link":"http://example.net/"}]
select --table Site --output_columns _key,title,link._key,link.title --query title:@this
# [[0, 1337566253.89858, 0.000355720520019531], 1]
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "title",
#           "ShortText"
#         ],
#         [
#           "link._key",
#           "ShortText"
#         ],
#         [
#           "link.title",
#           "ShortText"
#         ]
#       ],
#       [
#         "http://example.org/",
#         "This is test record 1!",
#         "http://example.net/",
#         "test record 2."
#       ]
#     ]
#   ]
# ]

テーブル参照のカラムを作成するときは、 /reference/commands/column_create コマンドの type 引数に参照先テーブルを指定します。この例では、同じテーブルに含まれる別のレコードを参照させたいので、Siteを指定することになります。次に、 "http://example.org/" から "http://example.net/" へのリンクを登録しています。テーブル参照を作成するときは、IDではなく主キーを指定することに注意してください。最後に、リンクの内容を確認しています。この例では、 output_columns 引数に link._key と link.title を指定しているので、参照先の主キーとタイトルが表示されています。

  ベクターカラム

/reference/commands/column_create コマンドでカラムを作成するとき、 flags 引数にCOLUMN_VECTORフラグを指定すると、 type 引数に指定した型の配列を格納するカラムになります。このようなカラムのことは、ベクターカラムと呼びます。ベクターカラムは、各レコードに複数の値を格納できるため、一対多の参照関係を表すのに便利です。

さきほどテーブル参照の例として作成したカラムでは、各サイトに一つのリンクしか保存できませんでした。通常は一つのサイトから多くのサイトにリンクが張られているので、これでは残念な仕様になってしまいます。そこで、ベクターカラムを使って、複数のリンクを保存できるようにしてみましょう。

実行例:

column_create --table Site --name links --flags COLUMN_VECTOR --type Site
# [[0, 1337566253.89858, 0.000355720520019531], true]
load --table Site
[{"_key":"http://example.org/","links":["http://example.net/","http://example.org/","http://example.com/"]}]
select --table Site --output_columns _key,title,links._key,links.title --query title:@this
# [[0, 1337566253.89858, 0.000355720520019531], 1]
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "title",
#           "ShortText"
#         ],
#         [
#           "links._key",
#           "ShortText"
#         ],
#         [
#           "links.title",
#           "ShortText"
#         ]
#       ],
#       [
#         "http://example.org/",
#         "This is test record 1!",
#         [
#           "http://example.net/",
#           "http://example.org/",
#           "http://example.com/"
#         ],
#         [
#           "test record 2.",
#           "This is test record 1!",
#           "test test record three."
#         ]
#       ]
#     ]
#   ]
# ]

新たなカラムにはSiteテーブルに対する参照の配列を格納するので、 type 引数にSiteを指定するとともに、 flags 引数にCOLUMN_VECTORフラグを指定しています。次に、 /reference/commands/load による更新では、 "http://example.org/" から "http://example.net/" へのリンクに加えて、 "http://example.org/" と "http://example.com/" へのリンクも登録しています。そして、最後にリンクの内容を確認しています。この例では、 output_columns 引数に links._key と links.title を指定しているので、参照先の主キーとタイトルをそれぞれ配列にしたものが表示されています。

  さまざまな検索条件の指定

groongaは、JavaScriptに似た文法での条件絞込や、計算した値を用いたソートを行うことができます。また、位置情報(緯度・経度)を用いた絞込・ソートを行うことができます。

  JavaScriptに似た文法での絞込・全文検索

selectコマンドのfilterパラメータは、queryパラメータと同様に、レコードの検索条件を指定します。filterパラメータとqueryパラメータが異なる点は、filterパラメータには、JavaScriptの式に似た文法で条件を指定する点です。

実行例:

select --table Site --filter "_id <= 1" --output_columns _id,_key
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ]
#       ],
#       [
#         1,
#         "http://example.org/"
#       ]
#     ]
#   ]
# ]

ここで、filterパラメータには _id <= 1

という条件を指定しています。この場合は_idの値が1以下のレコードが検索結果として得られます。

また、&& や || を使って、条件のAND・OR指定をすることもできます。

実行例:

select --table Site --filter "_id >= 4 && _id <= 6" --output_columns _id,_key
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         3
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ]
#       ],
#       [
#         4,
#         "http://example.net/afr"
#       ],
#       [
#         5,
#         "http://example.org/aba"
#       ],
#       [
#         6,
#         "http://example.com/rab"
#       ]
#     ]
#   ]
# ]
select --table Site --filter "_id <= 2 || _id >= 7" --output_columns _id,_key
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         5
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ]
#       ],
#       [
#         1,
#         "http://example.org/"
#       ],
#       [
#         2,
#         "http://example.net/"
#       ],
#       [
#         7,
#         "http://example.net/atv"
#       ],
#       [
#         8,
#         "http://example.org/gat"
#       ],
#       [
#         9,
#         "http://example.com/vdw"
#       ]
#     ]
#   ]
# ]

queryパラメータとfilterパラメータを同時に指定すると、両者の条件をともに満たすレコードが結果として返ります。

  scorerを利用したソート

selectコマンドのscorerパラメータは、 全文検索を行った結果の各レコードに対して処理を行うためのパラメータです。

filterパラメータと同様に、 JavaScriptの式に似たな文法で様々な条件を指定することができます。

実行例:

select --table Site --filter "1" --scorer "_score = rand()" --output_columns _id,_key,_score --sortby _score
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         9
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "_score",
#           "Int32"
#         ]
#       ],
#       [
#         6,
#         "http://example.com/rab",
#         424238335
#       ],
#       [
#         9,
#         "http://example.com/vdw",
#         596516649
#       ],
#       [
#         7,
#         "http://example.net/atv",
#         719885386
#       ],
#       [
#         2,
#         "http://example.net/",
#         846930886
#       ],
#       [
#         8,
#         "http://example.org/gat",
#         1649760492
#       ],
#       [
#         3,
#         "http://example.com/",
#         1681692777
#       ],
#       [
#         4,
#         "http://example.net/afr",
#         1714636915
#       ],
#       [
#         1,
#         "http://example.org/",
#         1804289383
#       ],
#       [
#         5,
#         "http://example.org/aba",
#         1957747793
#       ]
#     ]
#   ]
# ]
select --table Site --filter "1" --scorer "_score = rand()" --output_columns _id,_key,_score --sortby _score
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         9
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "_score",
#           "Int32"
#         ]
#       ],
#       [
#         4,
#         "http://example.net/afr",
#         783368690
#       ],
#       [
#         2,
#         "http://example.net/",
#         1025202362
#       ],
#       [
#         5,
#         "http://example.org/aba",
#         1102520059
#       ],
#       [
#         1,
#         "http://example.org/",
#         1189641421
#       ],
#       [
#         3,
#         "http://example.com/",
#         1350490027
#       ],
#       [
#         8,
#         "http://example.org/gat",
#         1365180540
#       ],
#       [
#         9,
#         "http://example.com/vdw",
#         1540383426
#       ],
#       [
#         7,
#         "http://example.net/atv",
#         1967513926
#       ],
#       [
#         6,
#         "http://example.com/rab",
#         2044897763
#       ]
#     ]
#   ]
# ]

検索結果には、'_score'という名前の、全文検索のスコアが代入されている仮想的なカラムが付与されることをチュートリアル中ソートの項目で説明しました。

上記の実行例では、scorerパラメータに _score = rand()

という条件を指定しています。ここでは、rand()という乱数を返す関数を用いて、全文検索のスコアを乱数で上書きしています。

sortbyパラメータには、 _score

を指定しています。これは、スコア順に昇順にソートすることを意味しています。

よって、上記のクエリは実行されるたびに検索結果の並び順がランダムに変わります。

  位置情報を用いた絞込・ソート

groongaでは、位置情報（経緯度）を保存することができます。また、保存した経緯度を用いて絞込やソートができます。

位置情報を保存するためのカラムの型として、TokyoGeoPoint/WGS84GeoPointの２つの型があります。前者は日本測地系、後者は世界測地系(WGS84相当)の経緯度を保存します。

経緯度は以下のいずれかの形式の文字列として指定します。

•   "[緯度のミリ秒]x[経度のミリ秒]"（例: "128452975x503157902"）

•   "[緯度のミリ秒],[経度のミリ秒]"（例: "128452975,503157902"）

•   "[緯度の小数表記の度数]x[経度の小数表記の度数]"（例: "35.6813819x139.7660839"）

•   "[緯度の小数表記の度数],[経度の小数表記の度数]"（例: "35.6813819,139.7660839"）

    ここでは、ためしに東京駅と新宿駅とついて、世界測地系での位置情報を保存してみましょう。東京駅は緯度が35度40分52.975秒、経度が139度45分57.902秒です。新宿駅は緯度が35度41分27.316秒、経度が139度42分0.929秒です。よって、ミリ秒表記の場合はそれぞれ"128452975x503157902"/"128487316x502920929"となります。度数表記の場合はそれぞれ"35.6813819x139.7660839"/"35.6909211x139.7002581"となります。ここではミリ秒表記で登録しましょう。

    実行例:

    column_create --table Site --name location --type WGS84GeoPoint
    # [[0, 1337566253.89858, 0.000355720520019531], true]
    load --table Site
    [
     {"_key":"http://example.org/","location":"128452975x503157902"}
     {"_key":"http://example.net/","location":"128487316x502920929"},
    ]
    # [[0, 1337566253.89858, 0.000355720520019531], 2]
    select --table Site --query "_id:1 OR _id:2" --output_columns _key,location
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         2
    #       ],
    #       [
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "location",
    #           "WGS84GeoPoint"
    #         ]
    #       ],
    #       [
    #         "http://example.org/",
    #         "128452975x503157902"
    #       ],
    #       [
    #         "http://example.net/",
    #         "128487316x502920929"
    #       ]
    #     ]
    #   ]
    # ]

    scorerパラメータにおいて、 /reference/functions/geo_distance 関数を用いることにより、２点間の距離を計算することができます。

    ここでは、秋葉原駅からの距離を表示させてみましょう。世界測地系では、秋葉原駅の位置は緯度が35度41分55.259秒、経度が139度46分27.188秒です。よって、geo_distance関数に与える文字列は"128515259x503187188"となります。

    実行例:

    select --table Site --query "_id:1 OR _id:2" --output_columns _key,location,_score --scorer '_score = geo_distance(location, "128515259x503187188")'
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         2
    #       ],
    #       [
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "location",
    #           "WGS84GeoPoint"
    #         ],
    #         [
    #           "_score",
    #           "Int32"
    #         ]
    #       ],
    #       [
    #         "http://example.org/",
    #         "128452975x503157902",
    #         2054
    #       ],
    #       [
    #         "http://example.net/",
    #         "128487316x502920929",
    #         6720
    #       ]
    #     ]
    #   ]
    # ]

    この結果を見ると、東京駅と秋葉原駅は2054m、秋葉原駅と新宿駅は6720m離れているようです。

    geo_distance関数は、_scoreを通じてソートでも用いることができます。

    実行例:

    select --table Site --query "_id:1 OR _id:2" --output_columns _key,location,_score --scorer '_score = geo_distance(location, "128515259x503187188")' --sortby -_score
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         2
    #       ],
    #       [
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "location",
    #           "WGS84GeoPoint"
    #         ],
    #         [
    #           "_score",
    #           "Int32"
    #         ]
    #       ],
    #       [
    #         "http://example.net/",
    #         "128487316x502920929",
    #         6720
    #       ],
    #       [
    #         "http://example.org/",
    #         "128452975x503157902",
    #         2054
    #       ]
    #     ]
    #   ]
    # ]

    「ある地点から何m以内に存在する」といった絞込も可能です。

    filterパラメータにおいて、 /reference/functions/geo_in_circle 関数を用いることにより、２点間の距離が指定のm以下におさまるかどうかを判定することができます。

    たとえば、秋葉原駅から5000m以内にあるレコードを検索してみましょう。

    実行例:

    select --table Site --output_columns _key,location --filter 'geo_in_circle(location, "128515259x503187188", 5000)'
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         1
    #       ],
    #       [
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "location",
    #           "WGS84GeoPoint"
    #         ]
    #       ],
    #       [
    #         "http://example.org/",
    #         "128452975x503157902"
    #       ]
    #     ]
    #   ]
    # ]

    また、経緯度が指定の矩形領域内であるかどうかを判定する /reference/functions/geo_in_rectangle 関数も存在します。

  ドリルダウン

groongaでは、特定のカラム値で検索結果をグループ化することができます。これをドリルダウンと呼びます。

Siteテーブルに２つのカラムを追加します。TLDドメイン名を格納するdomainカラムと、国名を格納するcountryカラムです。これらのカラムの型は、それぞれドメイン名を主キーとするSiteDomainテーブルと、国名を主キーとするSiteCountryテーブルとします。

実行例:

table_create --name SiteDomain --flags TABLE_HASH_KEY --key_type ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
table_create --name SiteCountry --flags TABLE_HASH_KEY --key_type ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create --table Site --name domain --flags COLUMN_SCALAR --type SiteDomain
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create --table Site --name country --flags COLUMN_SCALAR --type SiteCountry
# [[0, 1337566253.89858, 0.000355720520019531], true]
load --table Site
[
{"_key":"http://example.org/","domain":".org","country":"japan"},
{"_key":"http://example.net/","domain":".net","country":"brazil"},
{"_key":"http://example.com/","domain":".com","country":"japan"},
{"_key":"http://example.net/afr","domain":".net","country":"usa"},
{"_key":"http://example.org/aba","domain":".org","country":"korea"},
{"_key":"http://example.com/rab","domain":".com","country":"china"},
{"_key":"http://example.net/atv","domain":".net","country":"china"},
{"_key":"http://example.org/gat","domain":".org","country":"usa"},
{"_key":"http://example.com/vdw","domain":".com","country":"japan"}
]
# [[0, 1337566253.89858, 0.000355720520019531], 9]

domainカラムとcountryカラムでドリルダウンを行う例を以下に示します。

実行例:

select --table Site --limit 0 --drilldown domain
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         9
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "country",
#           "SiteCountry"
#         ],
#         [
#           "domain",
#           "SiteDomain"
#         ],
#         [
#           "link",
#           "Site"
#         ],
#         [
#           "links",
#           "Site"
#         ],
#         [
#           "location",
#           "WGS84GeoPoint"
#         ],
#         [
#           "title",
#           "ShortText"
#         ]
#       ]
#     ],
#     [
#       [
#         3
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "_nsubrecs",
#           "Int32"
#         ]
#       ],
#       [
#         ".org",
#         3
#       ],
#       [
#         ".net",
#         3
#       ],
#       [
#         ".com",
#         3
#       ]
#     ]
#   ]
# ]

テーブル型を持つカラムに対してドリルダウンを行った場合、参照先のテーブルに存在するカラム値を取得することもできます。ドリルダウンを行ったテーブルには、_nsubrecsという仮想的なカラムが追加されます。このカラムには、グループ化されたレコード数が入ります。

実行例:

select --table Site --limit 0 --drilldown domain --drilldown_output_columns _id,_key,_nsubrecs
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         9
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "country",
#           "SiteCountry"
#         ],
#         [
#           "domain",
#           "SiteDomain"
#         ],
#         [
#           "link",
#           "Site"
#         ],
#         [
#           "links",
#           "Site"
#         ],
#         [
#           "location",
#           "WGS84GeoPoint"
#         ],
#         [
#           "title",
#           "ShortText"
#         ]
#       ]
#     ],
#     [
#       [
#         3
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "_nsubrecs",
#           "Int32"
#         ]
#       ],
#       [
#         1,
#         ".org",
#         3
#       ],
#       [
#         2,
#         ".net",
#         3
#       ],
#       [
#         3,
#         ".com",
#         3
#       ]
#     ]
#   ]
# ]

複数のカラムに対してドリルダウンを行うことができます。複数のカラムに対してドリルダウンを行う場合には、drilldownパラメータにカラム名をカンマ区切りで与えます。

実行例:

select --table Site --limit 0 --drilldown domain,country
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         9
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "country",
#           "SiteCountry"
#         ],
#         [
#           "domain",
#           "SiteDomain"
#         ],
#         [
#           "link",
#           "Site"
#         ],
#         [
#           "links",
#           "Site"
#         ],
#         [
#           "location",
#           "WGS84GeoPoint"
#         ],
#         [
#           "title",
#           "ShortText"
#         ]
#       ]
#     ],
#     [
#       [
#         3
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "_nsubrecs",
#           "Int32"
#         ]
#       ],
#       [
#         ".org",
#         3
#       ],
#       [
#         ".net",
#         3
#       ],
#       [
#         ".com",
#         3
#       ]
#     ],
#     [
#       [
#         5
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "_nsubrecs",
#           "Int32"
#         ]
#       ],
#       [
#         "japan",
#         3
#       ],
#       [
#         "brazil",
#         1
#       ],
#       [
#         "usa",
#         2
#       ],
#       [
#         "korea",
#         1
#       ],
#       [
#         "china",
#         2
#       ]
#     ]
#   ]
# ]

ドリルダウン結果を並びかえることができます。例えば、_nsubrecsパラメータの降順で並び替えることができます。

実行例:

select --table Site --limit 0 --drilldown country --drilldown_sortby _nsubrecs
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         9
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "country",
#           "SiteCountry"
#         ],
#         [
#           "domain",
#           "SiteDomain"
#         ],
#         [
#           "link",
#           "Site"
#         ],
#         [
#           "links",
#           "Site"
#         ],
#         [
#           "location",
#           "WGS84GeoPoint"
#         ],
#         [
#           "title",
#           "ShortText"
#         ]
#       ]
#     ],
#     [
#       [
#         5
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "_nsubrecs",
#           "Int32"
#         ]
#       ],
#       [
#         "brazil",
#         1
#       ],
#       [
#         "korea",
#         1
#       ],
#       [
#         "usa",
#         2
#       ],
#       [
#         "china",
#         2
#       ],
#       [
#         "japan",
#         3
#       ]
#     ]
#   ]
# ]

ドリルダウン結果は、デフォルトでは10件のみ表示されます。drilldown_offsetパラメータと、drilldown_limitパラメータによって、offsetとlimitを指定することができます。

実行例:

select --table Site --limit 0 --drilldown country --drilldown_sortby _nsubrecs --drilldown_limit 2 --drilldown_offset 2
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         9
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "country",
#           "SiteCountry"
#         ],
#         [
#           "domain",
#           "SiteDomain"
#         ],
#         [
#           "link",
#           "Site"
#         ],
#         [
#           "links",
#           "Site"
#         ],
#         [
#           "location",
#           "WGS84GeoPoint"
#         ],
#         [
#           "title",
#           "ShortText"
#         ]
#       ]
#     ],
#     [
#       [
#         5
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "_nsubrecs",
#           "Int32"
#         ]
#       ],
#       [
#         "usa",
#         2
#       ],
#       [
#         "china",
#         2
#       ]
#     ]
#   ]
# ]

文字列型のカラムに対するドリルダウンは、他の型でのドリルダウンに比べて低速です。文字列でのドリルダウンを行いたい場合には、このチュートリアルのように、文字列型を主キーとするテーブルを別途作成し、そのテーブルを型とするカラムを作成します。

  タグ検索・参照関係の逆引き

本チュートリアルで、groongaはカラム値として他のテーブルへの参照の配列を持つことができることを紹介いたしました。実は、テーブルへの参照の配列データを用いることによって、いわゆるタグ検索を行うことが可能となります。

タグ検索はgroongaの転置インデックスというデータ構造を用いて高速に行われます。

  タグ検索

動画共有サイトの検索エンジンを作ることを想定します。1つの動画には、その動画の特徴を表す、複数の語句が付与されています。「ある語句が付与されている動画の一覧を取得する」検索を行いたいとします。

実際に、動画情報のテーブルを作成し、検索をしてみましょう。

動画の情報を保存する、Videoテーブルを作成します。Videoテーブルでは、動画のタイトルをtitleカラムに、動画のタグ情報をtagsカラムにTagテーブル型で複数格納しています。 タグの情報を保存する、Tagテーブルを作成します。Tagテーブルでは、タグ文字列を主キーに格納し、Videoテーブルのtagsカラムに対するインデックスをindex_tagsカラムに格納しています。

実行例:

table_create --name Video --flags TABLE_HASH_KEY --key_type UInt32
# [[0, 1337566253.89858, 0.000355720520019531], true]
table_create --name Tag --flags TABLE_HASH_KEY --key_type ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create --table Video --name title --flags COLUMN_SCALAR --type ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create --table Video --name tags --flags COLUMN_VECTOR --type Tag
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create --table Tag --name index_tags --flags COLUMN_INDEX --type Video --source tags
# [[0, 1337566253.89858, 0.000355720520019531], true]
load --table Video
[
{"_key":1,"title":"Soccer 2010","tags":["Sports","Soccer"]},
{"_key":2,"title":"Zenigata Kinjirou","tags":["Variety","Money"]},
{"_key":3,"title":"groonga Demo","tags":["IT","Server","groonga"]},
{"_key":4,"title":"Moero!! Ultra Baseball","tags":["Sports","Baseball"]},
{"_key":5,"title":"Hex Gone!","tags":["Variety","Quiz"]},
{"_key":6,"title":"Pikonyan 1","tags":["Animation","Pikonyan"]},
{"_key":7,"title":"Draw 8 Month","tags":["Animation","Raccoon"]},
{"_key":8,"title":"K.O.","tags":["Animation","Music"]}
]
# [[0, 1337566253.89858, 0.000355720520019531], 8]

インデックスカラムを作成すると、全文検索が高速に行えるようになります。インデックスカラムは、対象のカラムに保存されたデータに更新があったとき、自動的に更新されます。

「ある語句が付与されている動画の一覧を取得する」検索を行いましょう。

実行例:

select --table Video --query tags:@Variety --output_columns _key,title
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_key",
#           "UInt32"
#         ],
#         [
#           "title",
#           "ShortText"
#         ]
#       ],
#       [
#         2,
#         "Zenigata Kinjirou"
#       ],
#       [
#         5,
#         "Hex Gone!"
#       ]
#     ]
#   ]
# ]
select --table Video --query tags:@Sports --output_columns _key,title
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_key",
#           "UInt32"
#         ],
#         [
#           "title",
#           "ShortText"
#         ]
#       ],
#       [
#         1,
#         "Soccer 2010"
#       ],
#       [
#         4,
#         "Moero!! Ultra Baseball"
#       ]
#     ]
#   ]
# ]
select --table Video --query tags:@Animation --output_columns _key,title
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         3
#       ],
#       [
#         [
#           "_key",
#           "UInt32"
#         ],
#         [
#           "title",
#           "ShortText"
#         ]
#       ],
#       [
#         6,
#         "Pikonyan 1"
#       ],
#       [
#         7,
#         "Draw 8 Month"
#       ],
#       [
#         8,
#         "K.O."
#       ]
#     ]
#   ]
# ]

このように、「Variety」、「Sports」、「Animation」のようなタグで検索を行うことができました。

  参照関係の逆引き

groongaはテーブル間の参照関係の逆引きを高速に行うためのインデックスを付与することができます。タグ検索は、その1例にすぎません。

例えば、ソーシャルネットワーキングサイトにおける友人関係を逆引き検索することができます。

以下の例では、ユーザー情報を格納するUserテーブルを作成し、ユーザー名を格納するusernameカラム、ユーザーの友人一覧を配列で格納するfriendsカラムとそのインデックスのindex_friendsカラムを追加しています。

実行例:

table_create --name User --flags TABLE_HASH_KEY --key_type ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create --table User --name username --flags COLUMN_SCALAR --type ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create --table User --name friends --flags COLUMN_VECTOR --type User
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create --table User --name index_friends --flags COLUMN_INDEX --type User --source friends
# [[0, 1337566253.89858, 0.000355720520019531], true]
load --table User
[
{"_key":"ken","username":"健作","friends":["taro","jiro","tomo","moritapo"]}
{"_key":"moritapo","username":"森田","friends":["ken","tomo"]}
{"_key":"taro","username":"ぐるんが太郎","friends":["jiro","tomo"]}
{"_key":"jiro","username":"ぐるんが次郎","friends":["taro","tomo"]}
{"_key":"tomo","username":"トモちゃん","friends":["ken","hana"]}
{"_key":"hana","username":"花子","friends":["ken","taro","jiro","moritapo","tomo"]}
]
# [[0, 1337566253.89858, 0.000355720520019531], 6]

指定したユーザーを友人リストに入れているユーザーの一覧を表示してみましょう。

実行例:

select --table User --query friends:@tomo --output_columns _key,username
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         5
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "username",
#           "ShortText"
#         ]
#       ],
#       [
#         "ken",
#         "健作"
#       ],
#       [
#         "taro",
#         "ぐるんが太郎"
#       ],
#       [
#         "jiro",
#         "ぐるんが次郎"
#       ],
#       [
#         "moritapo",
#         "森田"
#       ],
#       [
#         "hana",
#         "花子"
#       ]
#     ]
#   ]
# ]
select --table User --query friends:@jiro --output_columns _key,username
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         3
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "username",
#           "ShortText"
#         ]
#       ],
#       [
#         "ken",
#         "健作"
#       ],
#       [
#         "taro",
#         "ぐるんが太郎"
#       ],
#       [
#         "hana",
#         "花子"
#       ]
#     ]
#   ]
# ]

さらに、ドリルダウンを使って、友人リストに入っている数の一覧を表示してみましょう。

実行例:

select --table User --limit 0 --drilldown friends
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         6
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "friends",
#           "User"
#         ],
#         [
#           "index_friends",
#           "User"
#         ],
#         [
#           "username",
#           "ShortText"
#         ]
#       ]
#     ],
#     [
#       [
#         6
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "_nsubrecs",
#           "Int32"
#         ]
#       ],
#       [
#         "taro",
#         3
#       ],
#       [
#         "jiro",
#         3
#       ],
#       [
#         "tomo",
#         5
#       ],
#       [
#         "moritapo",
#         2
#       ],
#       [
#         "ken",
#         3
#       ],
#       [
#         "hana",
#         1
#       ]
#     ]
#   ]
# ]

このように、テーブルの参照関係を逆にたどる検索ができました。

  インデックス付きジオサーチ

位置情報のカラムに対して、インデックスを付与することが出来ます。大量の位置情報レコードを検索する場合に、検索速度が速くなります。

実行例:

table_create --name GeoIndex --flags TABLE_PAT_KEY --key_type WGS84GeoPoint
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create --table GeoIndex --name index_point --type Site --flags COLUMN_INDEX --source location
# [[0, 1337566253.89858, 0.000355720520019531], true]
load --table Site
[
 {"_key":"http://example.org/","location":"128452975x503157902"},
 {"_key":"http://example.net/","location":"128487316x502920929"}
]
# [[0, 1337566253.89858, 0.000355720520019531], 2]
select --table Site --filter 'geo_in_circle(location, "128515259x503187188", 5000)' --output_columns _key,location
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "location",
#           "WGS84GeoPoint"
#         ]
#       ],
#       [
#         "http://example.org/",
#         "128452975x503157902"
#       ]
#     ]
#   ]
# ]

同様に、位置情報レコードを用いてソートする場合に、ソート速度が速くなります。

実行例:

select --table Site --filter 'geo_in_circle(location, "128515259x503187188", 50000)' --output_columns _key,location,_score --sortby '-geo_distance(location, "128515259x503187188")' --scorer '_score = geo_distance(location, "128515259x503187188")'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "location",
#           "WGS84GeoPoint"
#         ],
#         [
#           "_score",
#           "Int32"
#         ]
#       ],
#       [
#         "http://example.org/",
#         "128452975x503157902",
#         2054
#       ],
#       [
#         "http://example.net/",
#         "128487316x502920929",
#         6720
#       ]
#     ]
#   ]
# ]

  match_columnsパラメータ

  複数のカラムを対象とした全文検索

groongaでは、複数のカラムを対象とした全文検索を行うことができます。例えば、ブログのテーブルで、タイトルと内容とがそれぞれ別のカラムに入ったものがあるとしましょう。「タイトルもしくは内容に特定の単語を含む」検索を行いたいとします。

この場合、2つのインデックス作成方式があります。1つは、それぞれのカラムに1つずつインデックスを付与する方式です。もう1つは、複数のカラムに対して1つのインデックスを付与する方式です。groongaでは、どちらの形式のインデックスが存在している場合でも、同一の記法で全文検索を行うことができます。

  カラムごとにインデックスを付与する場合

Blog1テーブルを作り、タイトル文字列のtitleカラム、本文のmessageカラムを追加しています。 インデックス用のIndexBlog1テーブルも作り、titleカラムのインデックス用にindex_titleカラム、messageカラムのインデック用にindex_messageカラムと、それぞれ1カラムごとに1つずつ追加しています。

実行例:

table_create --name Blog1 --flags TABLE_HASH_KEY --key_type ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create --table Blog1 --name title --flags COLUMN_SCALAR --type ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create --table Blog1 --name message --flags COLUMN_SCALAR --type ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
table_create --name IndexBlog1 --flags TABLE_PAT_KEY|KEY_NORMALIZE --key_type ShortText --default_tokenizer TokenBigram
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create --table IndexBlog1 --name index_title --flags COLUMN_INDEX|WITH_POSITION --type Blog1 --source title
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create --table IndexBlog1 --name index_message --flags COLUMN_INDEX|WITH_POSITION --type Blog1 --source message
# [[0, 1337566253.89858, 0.000355720520019531], true]
load --table Blog1
[
{"_key":"grn1","title":"groonga test","message":"groonga message"},
{"_key":"grn2","title":"baseball result","message":"rakutan eggs 4 - 4 groonga moritars"},
{"_key":"grn3","title":"groonga message","message":"none"}
]
# [[0, 1337566253.89858, 0.000355720520019531], 3]

match_columnsオプションで、検索対象のカラムを複数指定することが出来ます。検索する文字列はqueryオプションで指定します。これを使うことで、タイトルと本文を全文検索することができます。

実際に検索してみましょう。

実行例:

select --table Blog1 --match_columns title||message --query groonga
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         3
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "message",
#           "ShortText"
#         ],
#         [
#           "title",
#           "ShortText"
#         ]
#       ],
#       [
#         1,
#         "grn1",
#         "groonga message",
#         "groonga test"
#       ],
#       [
#         3,
#         "grn3",
#         "none",
#         "groonga message"
#       ],
#       [
#         2,
#         "grn2",
#         "rakutan eggs 4 - 4 groonga moritars",
#         "baseball result"
#       ]
#     ]
#   ]
# ]
select --table Blog1 --match_columns title||message --query message
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "message",
#           "ShortText"
#         ],
#         [
#           "title",
#           "ShortText"
#         ]
#       ],
#       [
#         3,
#         "grn3",
#         "none",
#         "groonga message"
#       ],
#       [
#         1,
#         "grn1",
#         "groonga message",
#         "groonga test"
#       ]
#     ]
#   ]
# ]
select --table Blog1 --match_columns title --query message
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "message",
#           "ShortText"
#         ],
#         [
#           "title",
#           "ShortText"
#         ]
#       ],
#       [
#         3,
#         "grn3",
#         "none",
#         "groonga message"
#       ]
#     ]
#   ]
# ]

  複数のカラムにまたがったインデックスを付与する場合

内容は上の例とほぼ同じですが、titleとmessageの2つのカラムに対するインデックスが共通になっており、インデックスカラムが1つしかありません。

共通のインデックスを用いても、titleカラムのみでの検索、messageカラムのみでの検索、titleもしくはmessageカラムでの検索、全ての検索を行うことができます。

実行例:

table_create --name Blog2 --flags TABLE_HASH_KEY --key_type ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create --table Blog2 --name title --flags COLUMN_SCALAR --type ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create --table Blog2 --name message --flags COLUMN_SCALAR --type ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
table_create --name IndexBlog2 --flags TABLE_PAT_KEY|KEY_NORMALIZE --key_type ShortText --default_tokenizer TokenBigram
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create --table IndexBlog2 --name index_blog --flags COLUMN_INDEX|WITH_POSITION|WITH_SECTION --type Blog2 --source title,message
# [[0, 1337566253.89858, 0.000355720520019531], true]
load --table Blog2
[
{"_key":"grn1","title":"groonga test","message":"groonga message"},
{"_key":"grn2","title":"baseball result","message":"rakutan eggs 4 - 4 groonga moritars"},
{"_key":"grn3","title":"groonga message","message":"none"}
]
# [[0, 1337566253.89858, 0.000355720520019531], 3]

実際に検索してみましょう。結果は上の例と同じになります。

実行例:

select --table Blog2 --match_columns title||message --query groonga
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         3
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "message",
#           "ShortText"
#         ],
#         [
#           "title",
#           "ShortText"
#         ]
#       ],
#       [
#         1,
#         "grn1",
#         "groonga message",
#         "groonga test"
#       ],
#       [
#         2,
#         "grn2",
#         "rakutan eggs 4 - 4 groonga moritars",
#         "baseball result"
#       ],
#       [
#         3,
#         "grn3",
#         "none",
#         "groonga message"
#       ]
#     ]
#   ]
# ]
select --table Blog2 --match_columns title||message --query message
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "message",
#           "ShortText"
#         ],
#         [
#           "title",
#           "ShortText"
#         ]
#       ],
#       [
#         1,
#         "grn1",
#         "groonga message",
#         "groonga test"
#       ],
#       [
#         3,
#         "grn3",
#         "none",
#         "groonga message"
#       ]
#     ]
#   ]
# ]
select --table Blog2 --match_columns title --query message
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "message",
#           "ShortText"
#         ],
#         [
#           "title",
#           "ShortText"
#         ]
#       ],
#       [
#         3,
#         "grn3",
#         "none",
#         "groonga message"
#       ]
#     ]
#   ]
# ]

  インデックス名を指定した全文検索

執筆中です。

  カラムインデックスによる関連テーブルをまたぐ検索

複数のテーブルがカラムインデックスで関連付けられているなら、参照カラム名を指定して複数のテーブルにまたがって検索することができます。

具体的な例を示します。

ブログ記事や記事のコメントを保存するテーブルがあります。記事を保存するテーブルには記事とコメントのためのカラムがあります。そしてそのコメントカラムはCommentsテーブルを参照しています。コメントを保存するテーブルにはコメントと記事テーブルに対するカラムインデックスが設定されています。

特定のキーワードをコメントに含む記事を探すには、コメントテーブルを全文検索する必要があり、全文検索結果を含むレコードをさらに検索する必要があります。

しかし、カラムインデックスを指定することで一度にレコードを検索することができます。

サンプルのスキーマ定義はこちらです。

実行例:

table_create Comments TABLE_HASH_KEY UInt32
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Comments content COLUMN_SCALAR ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
table_create Articles TABLE_NO_KEY
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Articles content COLUMN_SCALAR Text
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Articles comment COLUMN_SCALAR Comments
# [[0, 1337566253.89858, 0.000355720520019531], true]
table_create Lexicon TABLE_PAT_KEY|KEY_NORMALIZE ShortText --default_tokenizer TokenBigram
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Lexicon articles_content COLUMN_INDEX|WITH_POSITION Articles content
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Lexicon comments_content COLUMN_INDEX|WITH_POSITION Comments content
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Comments article COLUMN_INDEX Articles comment
# [[0, 1337566253.89858, 0.000355720520019531], true]

サンプルデータはこちらです。

実行例:

load --table Comments
[
{"_key": 1, "content": "I'm using groonga too!"},
{"_key": 2, "content": "I'm using groonga and mroonga!"},
{"_key": 3, "content": "I'm using mroonga too!"}
]
# [[0, 1337566253.89858, 0.000355720520019531], 3]
load --table Articles
[
{"content": "Groonga is fast!", "comment": 1},
{"content": "Groonga is useful!"},
{"content": "Mroonga is fast!", "comment": 3}
]
# [[0, 1337566253.89858, 0.000355720520019531], 3]

特定のキーワードをコメントに含むレコードを検索するクエリを書くことができ、それによりレコードを参照する記事を取得します。

これまでに記述したレコードを検索するクエリ:

select Articles --match_columns comment.content --query groonga --output_columns "_id, _score, *"

ArticlesテーブルのcommentカラムとCommentsテーブルのcontentカラムをピリオド(.)で連結し --match_columns の引数とする必要があります。

最初に、このクエリはCommentsテーブルのcontentを全文検索し、次にCommentsテーブルを検索した結果のレコードを参照するArticlesテーブルのレコードを取得します。(これにより、Commentsテーブルの'article'カラムインデックスを生成するクエリをコメントアウトすると、意図した検索結果が得られません。)

実行例:

select Articles --match_columns comment.content --query groonga --output_columns "_id, _score, *"
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_score",
#           "Int32"
#         ],
#         [
#           "comment",
#           "Comments"
#         ],
#         [
#           "content",
#           "Text"
#         ]
#       ],
#       [
#         1,
#         1,
#         1,
#         "Groonga is fast!"
#       ]
#     ]
#   ]
# ]

これで、特定のキーワードをコメントとして含む記事を検索できます。

このネストしたインデックスの検索という特徴には関連するテーブルが2つだけに制限されません。

前のものと似たサンプルのスキーマ定義です。違いは'返信'を表現するテーブルの追加と関連するテーブルが3つに増えたことです。

実行例:

table_create Replies2 TABLE_HASH_KEY UInt32
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Replies2 content COLUMN_SCALAR ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
table_create Comments2 TABLE_HASH_KEY UInt32
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Comments2 content COLUMN_SCALAR ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Comments2 comment COLUMN_SCALAR Replies2
# [[0, 1337566253.89858, 0.000355720520019531], true]
table_create Articles2 TABLE_NO_KEY
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Articles2 content COLUMN_SCALAR Text
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Articles2 comment COLUMN_SCALAR Comments2
# [[0, 1337566253.89858, 0.000355720520019531], true]
table_create Lexicon2 TABLE_PAT_KEY|KEY_NORMALIZE ShortText --default_tokenizer TokenBigram
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Lexicon2 articles_content COLUMN_INDEX|WITH_POSITION Articles2 content
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Lexicon2 comments_content COLUMN_INDEX|WITH_POSITION Comments2 content
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Lexicon2 replies_content COLUMN_INDEX|WITH_POSITION Replies2 content
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Comments2 article COLUMN_INDEX Articles2 comment
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Replies2 reply_to COLUMN_INDEX Comments2 comment
# [[0, 1337566253.89858, 0.000355720520019531], true]

サンプルデータはこちらです。

実行例:

load --table Replies2
[
{"_key": 1, "content": "I'm using rroonga too!"},
{"_key": 2, "content": "I'm using groonga and mroonga and rroonga!"},
{"_key": 3, "content": "I'm using nroonga too!"}
]
# [[0, 1337566253.89858, 0.000355720520019531], 3]
load --table Comments2
[
{"_key": 1, "content": "I'm using groonga too!", "comment": 1},
{"_key": 2, "content": "I'm using groonga and mroonga!", "comment": 2},
{"_key": 3, "content": "I'm using mroonga too!"}
]
# [[0, 1337566253.89858, 0.000355720520019531], 3]
load --table Articles2
[
{"content": "Groonga is fast!", "comment": 1},
{"content": "Groonga is useful!", "comment": 2},
{"content": "Mroonga is fast!", "comment": 3}
]
# [[0, 1337566253.89858, 0.000355720520019531], 3]

これまでに記述したレコードを検索するクエリ:

select Articles2 --match_columns comment.content --query mroonga --output_columns "_id, _score, *"
select Articles2 --match_columns comment.comment.content --query mroonga --output_columns "_id, _score, *"

最初のクエリはComments2テーブルから'mroonga'を検索します。2つめのクエリはReplies2とComments2テーブルからカラムインデックスによる参照を用いて'mroonga'を検索します。

実行例:

select Articles2 --match_columns comment.content --query mroonga --output_columns "_id, _score, *"
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_score",
#           "Int32"
#         ],
#         [
#           "comment",
#           "Comments2"
#         ],
#         [
#           "content",
#           "Text"
#         ]
#       ],
#       [
#         2,
#         1,
#         2,
#         "Groonga is useful!"
#       ],
#       [
#         3,
#         1,
#         3,
#         "Mroonga is fast!"
#       ]
#     ]
#   ]
# ]
select Articles2 --match_columns comment.comment.content --query mroonga --output_columns "_id, _score, *"
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_score",
#           "Int32"
#         ],
#         [
#           "comment",
#           "Comments2"
#         ],
#         [
#           "content",
#           "Text"
#         ]
#       ],
#       [
#         2,
#         1,
#         2,
#         "Groonga is useful!"
#       ]
#     ]
#   ]
# ]

結果として、最初のクエリはComments2テーブルに'mroonga'をキーワードとして含むレコードが2つあるので、該当する記事2つにマッチします。

一方、2つめのクエリはReplies2テーブルに'mroonga'というキーワードにマッチするレコードが1つしかなく、Comments2テーブルでそのキーワードを含むレコードを参照するコメントが1つなので、該当する記事は1つだけとなります。

  インデックスの重み

執筆中です。

  パトリシア木による前方一致検索

groongaのテーブルは、テーブル作成時にパトリシア木オプションを指定すると、前方一致検索を行うことができます。また、追加のオプションを指定することにより、主キーの後方一致検索をも行うことができます。

  主キーによる前方一致検索

table_createコマンドのflagsオプションにTABLE_PAT_KEYを指定することで、主キーによる前方一致検索ができるようになります。

実行例:

table_create --name PatPrefix --flags TABLE_PAT_KEY --key_type ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
load --table PatPrefix
[
{"_key":"ひろゆき"},
{"_key":"まろゆき"},
{"_key":"ひろあき"},
{"_key":"ゆきひろ"}
]
# [[0, 1337566253.89858, 0.000355720520019531], 4]
select --table PatPrefix --query _key:^ひろ
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ]
#       ],
#       [
#         1,
#         "ひろゆき"
#       ],
#       [
#         3,
#         "ひろあき"
#       ]
#     ]
#   ]
# ]

  主キーによる後方一致検索

table_createコマンドのflagsオプションにTABLE_PAT_KEYとKEY_WITH_SISを指定することで、主キーによる前方一致検索・後方一致検索の両方が可能となります。

KEY_WITH_SISフラグを付与すると、データを追加する際に後方一致用のレコードも追加されてしまいます。そのため、単純に検索すると、元のレコードに加えて自動的に追加されたレコードまでヒットしてしまいます。元のレコードのみ検索するために、一工夫必要になります。

例えば、元のレコードと自動的に追加されたレコードとの区別をつけるために、元のレコードであることを示すoriginalカラムを追加して、検索時にはoriginalカラムが true も検索条件に加えます。 --query オプションでは Bool 型の値を直感的に指定することができないので --filter オプションを使っていることに注意してください。

実行例:

table_create --name PatSuffix --flags TABLE_PAT_KEY|KEY_WITH_SIS --key_type ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create --table PatSuffix --name original --type Bool
# [[0, 1337566253.89858, 0.000355720520019531], true]
load --table PatSuffix
[
{"_key":"ひろゆき","original":true},
{"_key":"まろゆき","original":true},
{"_key":"ひろあき","original":true},
{"_key":"ゆきひろ","original":true}
]
# [[0, 1337566253.89858, 0.000355720520019531], 4]
select --table PatSuffix --query _key:$ゆき
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         4
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "original",
#           "Bool"
#         ]
#       ],
#       [
#         3,
#         "ゆき",
#         false
#       ],
#       [
#         2,
#         "ろゆき",
#         false
#       ],
#       [
#         5,
#         "まろゆき",
#         true
#       ],
#       [
#         1,
#         "ひろゆき",
#         true
#       ]
#     ]
#   ]
# ]
select --table PatSuffix --filter '_key @$ "ゆき" && original == true'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "original",
#           "Bool"
#         ]
#       ],
#       [
#         5,
#         "まろゆき",
#         true
#       ],
#       [
#         1,
#         "ひろゆき",
#         true
#       ]
#     ]
#   ]
# ]

  全文検索の語彙表に対する追加情報

groongaでは、全文検索に用いるための語意表がテーブルとして扱えます。よって、語彙ごとに複数の情報を保持することができます。例えば、語彙の出現数や検索ストップワードのフラグ、単語の重要度などを保持することができます。

この項目については、現在執筆中です。

  マイクロブログ検索システムの作成

これまで学んだgroongaの機能を用いて、マイクロブログの検索システムを作成してみましょう。マイクロブログとは、Twitterのような短いメッセージを投稿するブログです。

  テーブルの作成

まずは、テーブルを作成します。

table_create --name Users --flags TABLE_HASH_KEY --key_type ShortText
table_create --name Comments --flags TABLE_HASH_KEY --key_type ShortText
table_create --name HashTags --flags TABLE_HASH_KEY --key_type ShortText
table_create --name Bigram --flags TABLE_PAT_KEY|KEY_NORMALIZE --key_type ShortText --default_tokenizer TokenBigram
column_create --table Users --name name --flags COLUMN_SCALAR --type ShortText
column_create --table Users --name follower --flags COLUMN_VECTOR --type Users
column_create --table Users --name favorites --flags COLUMN_VECTOR --type Comments
column_create --table Users --name location --flags COLUMN_SCALAR --type WGS84GeoPoint
column_create --table Users --name location_str --flags COLUMN_SCALAR --type ShortText
column_create --table Users --name description --flags COLUMN_SCALAR --type ShortText
column_create --table Users --name followee --flags COLUMN_INDEX --type Users --source follower
column_create --table Comments --name comment --flags COLUMN_SCALAR --type ShortText
column_create --table Comments --name last_modified --flags COLUMN_SCALAR --type Time
column_create --table Comments --name replied_to --flags COLUMN_SCALAR --type Comments
column_create --table Comments --name replied_users --flags COLUMN_VECTOR --type Users
column_create --table Comments --name hash_tags --flags COLUMN_VECTOR --type HashTags
column_create --table Comments --name location --flags COLUMN_SCALAR --type WGS84GeoPoint
column_create --table Comments --name posted_by --flags COLUMN_SCALAR --type Users
column_create --table Comments --name favorited_by --flags COLUMN_INDEX --type Users --source favorites
column_create --table HashTags --name hash_index --flags COLUMN_INDEX --type Comments --source hash_tags
column_create --table Bigram --name users_index --flags COLUMN_INDEX|WITH_POSITION|WITH_SECTION --type Users --source name,location_str,description
column_create --table Bigram --name comment_index --flags COLUMN_INDEX|WITH_POSITION --type Comments --source comment

  Usersテーブル

ユーザーの名前や自己紹介文、フォローしているユーザー一覧など、ユーザー情報を格納するためのテーブルです。

_key
    ユーザーID

name
    ユーザー名

follower
    フォローしているユーザーの一覧

favorites
    お気に入りのコメント一覧

location
    ユーザーの現在地（緯度経度座標）

location_str
    ユーザーの現在地（文字列）

description
    ユーザーの自己紹介

followee
    Usersテーブルのfollowerカラムに対するインデックス。 このインデックスを作ることで、あるユーザーをフォローしているユーザーを検索できるようになります。

  Commentsテーブル

コメント内容や投稿日時、返信先情報など、コメントに関する内容を格納するテーブルです。

_key
    コメントID

comment
    コメント内容

last_modified
    投稿日時

replied_to
    返信元のコメント内容

replied_users
    返信先のユーザーの一覧

hash_tags
    コメントのハッシュタグの一覧

location
    投稿場所(緯度経度座標のため)

posted_by
    コメントを書いたユーザー

favorited_by
    Usersテーブルのfavoritesカラムに対するインデックス。 このインデックスを作ることで、指定したコメントを誰がお気に入りに入れているのかを検索できるようになります。

  HashTagsテーブル

コメントのハッシュタグを一覧で保存するためのテーブルです。

_key
    ハッシュタグ

hash_index
    「Comments.hash_tags」のインデックス。 このインデックスを作ることで、指定したハッシュタグのついているコメントの一覧を出すことが出来るようになります。

  Bigramテーブル

ユーザー情報・コメントで全文検索が出来るようにするためのインデックスを格納するテーブルです。

_key
    単語

users_index
    ユーザー情報のインデックス。 このカラムは、ユーザー名「Users.name」、現在地「Users.location_str」、自己紹介文「Users.description」のインデックスになっています。

comment_index
    コメント内容「Comments.comment」のインデックス

  データのロード

つづいて、テスト用データをロードします。

load --table Users
[
  {
    "_key": "daijiro",
    "name": "hsiomaneki",
    "follower": ["tasukuchan"],
    "favorites": [],
    "location": "127678039x502643091",
    "location_str": "神奈川県",
    "description": "groonga developer"
  },
  {
    "_key": "tasukuchan",
    "name": "グニャラくん",
    "follower": ["daijiro","OffGao"],
    "favorites": ["daijiro:1","OffGao:1"],
    "location": "128423343x502929252",
    "location_str": "東京都渋谷区",
    "description": "エロいおっさん"
  },
  {
    "_key": "OffGao",
    "name": "OffGao",
    "follower": ["tasukuchan","daijiro"],
    "favorites": ["tasukuchan:1","daijiro:1"],
    "location": "128544408x502801502",
    "location_str": "東京都中野区",
    "description": "がおがお"
  }
]
load --table Comments
[
  {
    "_key": "daijiro:1",
    "comment": "マイクロブログ作ってみました（甘栗むいちゃいました的な感じで）。",
    "last_modified": "2010/03/17 12:05:00",
    "posted_by": "daijiro",
  },
  {
    "_key": "tasukuchan:1",
    "comment": "初の書き込み。テストテスト。",
    "last_modified": "2010/03/17 12:00:00",
    "posted_by": "tasukuchan",
  },
  {
    "_key": "daijiro:2",
    "comment": "@tasukuchan ようこそ!!!",
    "last_modified": "2010/03/17 12:05:00",
    "replied_to": "tasukuchan:1",
    "replied_users": ["tasukuchan"],
    "posted_by": "daijiro",
  },
  {
    "_key": "tasukuchan:2",
    "comment": "@daijiro ありがとう！",
    "last_modified": "2010/03/17 13:00:00",
    "replied_to": "daijiro:2",
    "replied_users": ["daijiro"],
    "posted_by": "tasukuchan",
  },
  {
    "_key": "tasukuchan:3",
    "comment": "groongaなう #groonga",
    "last_modified": "2010/03/17 14:00:00",
    "hash_tags": ["groonga"],
    "location": "127972422x503117107",
    "posted_by": "tasukuchan",
  },
  {
    "_key": "tasukuchan:4",
    "comment": "groonga開発合宿のため羽田空港に来ました！ #groonga #travel",
    "last_modified": "2010/03/17 14:05:00",
    "hash_tags": ["groonga", "travel"],
    "location": "127975798x502919856",
    "posted_by": "tasukuchan",
  },
  {
    "_key": "OffGao:1",
    "comment": "@daijiro @tasukuchan 登録してみましたよー！",
    "last_modified": "2010/03/17 15:00:00",
    "replied_users": ["daijiro", "tasukuchan"],
    "location": "128551935x502796433",
    "posted_by": "OffGao",
  }
  {
    "_key": "OffGao:2",
    "comment": "中野ブロードウェイなうなう",
    "last_modified": "2010/03/17 15:05:00",
    "location": "128551935x502796434",
    "posted_by": "OffGao",
  }
]

Usersテーブルのfollowerカラムとfavoritesカラム、そしてCommentsテーブルのreplied_usersカラムは、ベクターカラムです。そのため、これらのカラムは配列で値を指定します。

Usersテーブルのlocationカラムと、Commentsテーブルのlocationカラムは、GeoPoint型です。この型での値の指定は、"[緯度]x[経度]"と記述して指定します。

Commentsテーブルのlast_modifiedカラムは、Time型です。この型での値を指定する方法は2つあります。 1つ目の方法は、1970年1月1日0時0分0秒からの経過秒数の値を直接指定する方法です。このとき、小数部分を指定することでマイクロ秒数での指定が可能です。指定した値は、データのロードの際にマイクロ秒を単位とする整数値に変換後、格納されます。 2つ目の方法は、文字列で日時と時刻を指定する方法です。"年/月/日 時:分:秒"というフォーマットで記述することで、データロードの際に文字列からキャストされ、マイクロ秒数の値が格納されます。

  検索

それでは、実際に検索をしてみましょう。

  キーワードでユーザー検索

ここでは、 match_columns で扱った、複数カラムを対象とした検索を行います。 指定された文字列で、ユーザー名・現在地・自己紹介文を対象に検索をします。

実行例:

select --table Users --match_columns name,location_str,description --query 東京 --output_columns _key,name
# [[0, 1337566253.89858, 0.000355720520019531], true]
# [[0, 1337566253.89858, 0.000355720520019531], true]
# [[0, 1337566253.89858, 0.000355720520019531], true]
# [[0, 1337566253.89858, 0.000355720520019531], true]
# [[0, 1337566253.89858, 0.000355720520019531], true]
# [[0, 1337566253.89858, 0.000355720520019531], true]
# [[0, 1337566253.89858, 0.000355720520019531], true]
# [[0, 1337566253.89858, 0.000355720520019531], true]
# [[0, 1337566253.89858, 0.000355720520019531], true]
# [[0, 1337566253.89858, 0.000355720520019531], true]
# [[0, 1337566253.89858, 0.000355720520019531], true]
# [[0, 1337566253.89858, 0.000355720520019531], true]
# [[0, 1337566253.89858, 0.000355720520019531], true]
# [[0, 1337566253.89858, 0.000355720520019531], true]
# [[0, 1337566253.89858, 0.000355720520019531], true]
# [[0, 1337566253.89858, 0.000355720520019531], true]
# [[0, 1337566253.89858, 0.000355720520019531], true]
# [[0, 1337566253.89858, 0.000355720520019531], true]
# [[0, 1337566253.89858, 0.000355720520019531], true]
# [[0, 1337566253.89858, 0.000355720520019531], true]
# [[0, 1337566253.89858, 0.000355720520019531], true]
# [[0, 1337566253.89858, 0.000355720520019531], true]
# [[0, 1337566253.89858, 0.000355720520019531], 3]
# [[0, 1337566253.89858, 0.000355720520019531], 8]
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "name",
#           "ShortText"
#         ]
#       ],
#       [
#         "tasukuchan",
#         "グニャラくん"
#       ],
#       [
#         "OffGao",
#         "OffGao"
#       ]
#     ]
#   ]
# ]

「東京」をキーワードにユーザー検索した結果、東京都に住んでいる「グニャラくん」と「OffGao」がヒットしました。

  GeoPointでユーザー検索

ここでは、 search で扱った、GeoPoint型のカラムで検索をします。 以下の例では、指定された位置から5000m以内にいるユーザーを検索しています。

実行例:

select --table Users --filter 'geo_in_circle(location,"128484216x502919856",5000)' --output_columns _key,name
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "name",
#           "ShortText"
#         ]
#       ],
#       [
#         "tasukuchan",
#         "グニャラくん"
#       ],
#       [
#         "OffGao",
#         "OffGao"
#       ]
#     ]
#   ]
# ]

新宿駅から5km以内にすんでいるユーザーを検索したところ、「グニャラくん」と「OffGao」がヒットしました。

  あるユーザーをフォローしているユーザーの検索

ここでは、 index で扱った、参照関係の逆引きをします。 以下の例では、Usersテーブルのfollowerカラムにあるフォローリストを逆引きします。

実行例:

select --table Users --query follower:@tasukuchan --output_columns _key,name
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "name",
#           "ShortText"
#         ]
#       ],
#       [
#         "daijiro",
#         "hsiomaneki"
#       ],
#       [
#         "OffGao",
#         "OffGao"
#       ]
#     ]
#   ]
# ]

「グニャラくん」をフォローしている「hsiomaneki」と「OffGao」がヒットしました。

  GeoPointでコメント検索

ある範囲内で書かれたコメントを検索します。 また、 drilldown で扱ったドリルダウンも行います。検索結果をハッシュタグとユーザーでドリルダウンし、ユーザー別・ハッシュタグ別のカウントを出します。

実行例:

select --table Comments --filter 'geo_in_circle(location,"127975798x502919856",20000)' --output_columns posted_by.name,comment --drilldown hash_tags,posted_by
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         4
#       ],
#       [
#         [
#           "posted_by.name",
#           "ShortText"
#         ],
#         [
#           "comment",
#           "ShortText"
#         ]
#       ],
#       [
#         "OffGao",
#         "@daijiro @tasukuchan 登録してみましたよー！"
#       ],
#       [
#         "グニャラくん",
#         "groongaなう #groonga"
#       ],
#       [
#         "グニャラくん",
#         "groonga開発合宿のため羽田空港に来ました！ #groonga #travel"
#       ],
#       [
#         "OffGao",
#         "中野ブロードウェイなうなう"
#       ]
#     ],
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "_nsubrecs",
#           "Int32"
#         ]
#       ],
#       [
#         "groonga",
#         2
#       ],
#       [
#         "travel",
#         1
#       ]
#     ],
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "_nsubrecs",
#           "Int32"
#         ]
#       ],
#       [
#         "OffGao",
#         2
#       ],
#       [
#         "tasukuchan",
#         2
#       ]
#     ]
#   ]
# ]

範囲を広く指定したため、位置情報のあるすべてのコメントがヒットしました。そして、ヒットしたコメントからドリルダウンされた結果も返ってきており、ハッシュタグは「#groonga」が2つに「#travel」が1つ、投稿者は「グニャラくん」「OffGao」がそれぞれ2件ずつであることがわかります。

  キーワードでコメント検索

あるキーワードを含むコメントを検索します。 さらに、 search で扱った、スコア値_scoreも出してみましょう。

実行例:

select --table Comments --query comment:@なう --output_columns comment,_score
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "comment",
#           "ShortText"
#         ],
#         [
#           "_score",
#           "Int32"
#         ]
#       ],
#       [
#         "groongaなう #groonga",
#         1
#       ],
#       [
#         "中野ブロードウェイなうなう",
#         2
#       ]
#     ]
#   ]
# ]

「なう」をキーワードにコメント検索した結果、2件のコメントがヒットしました。また、_scoreの値も返ってきており、「なう」の数が出力されていることが確認できます。

  GeoPointとキーワードでコメント検索

今度は、キーワードとGeoPointの両方を条件に検索をしてみます。--queryと--filterの両方を使用した場合、両方の条件に一致するレコードがヒットします。

実行例:

select --table Comments --query comment:@羽田 --filter 'geo_in_circle(location,"127975798x502919856",20000)' --output_columns posted_by.name,comment --drilldown hash_tags,posted_by
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "posted_by.name",
#           "ShortText"
#         ],
#         [
#           "comment",
#           "ShortText"
#         ]
#       ],
#       [
#         "グニャラくん",
#         "groonga開発合宿のため羽田空港に来ました！ #groonga #travel"
#       ]
#     ],
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "_nsubrecs",
#           "Int32"
#         ]
#       ],
#       [
#         "groonga",
#         1
#       ],
#       [
#         "travel",
#         1
#       ]
#     ],
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "_nsubrecs",
#           "Int32"
#         ]
#       ],
#       [
#         "tasukuchan",
#         1
#       ]
#     ]
#   ]
# ]

両方の条件を満たすコメントが1件ヒットしました。また、ドリルダウンの結果も返ってきており、「グニャラくん」のコメント1件であることがわかります。

  ハッシュタグでコメント検索

あるハッシュタグのついているコメントを検索します。 これも、 index で扱った、参照関係の逆引きを使います。

実行例:

select --table Comments --query hash_tags:@groonga --output_columns posted_by.name,comment --drilldown posted_by
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "posted_by.name",
#           "ShortText"
#         ],
#         [
#           "comment",
#           "ShortText"
#         ]
#       ],
#       [
#         "グニャラくん",
#         "groongaなう #groonga"
#       ],
#       [
#         "グニャラくん",
#         "groonga開発合宿のため羽田空港に来ました！ #groonga #travel"
#       ]
#     ],
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "_nsubrecs",
#           "Int32"
#         ]
#       ],
#       [
#         "tasukuchan",
#         2
#       ]
#     ]
#   ]
# ]

#groongaタグの付いている2件のコメントがヒットしました。また、投稿者のドリルダウンも返ってきており、2件とも「グニャラくん」のものであることがわかります。

  ユーザーIDでコメント検索

あるユーザーが投稿したコメントを検索します。

実行例:

select --table Comments --query posted_by:tasukuchan --output_columns comment --drilldown hash_tags
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         4
#       ],
#       [
#         [
#           "comment",
#           "ShortText"
#         ]
#       ],
#       [
#         "初の書き込み。テストテスト。"
#       ],
#       [
#         "@daijiro ありがとう！"
#       ],
#       [
#         "groongaなう #groonga"
#       ],
#       [
#         "groonga開発合宿のため羽田空港に来ました！ #groonga #travel"
#       ]
#     ],
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "_nsubrecs",
#           "Int32"
#         ]
#       ],
#       [
#         "groonga",
#         2
#       ],
#       [
#         "travel",
#         1
#       ]
#     ]
#   ]
# ]

「グニャラくん」が書き込んだ4件のコメントがヒットしました。また、ハッシュタグでドリルダウンした結果も返ってきており、ハッシュタグは「#groonga」が2つに「#travel」が1つあることがわかります。

  ユーザーのお気に入りコメントを検索

あるユーザーがお気に入りに入れているコメントを検索します。

実行例:

select --table Users --query _key:tasukuchan --output_columns favorites.posted_by,favorites.comment
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "favorites.posted_by",
#           "Users"
#         ],
#         [
#           "favorites.comment",
#           "ShortText"
#         ]
#       ],
#       [
#         [
#           "daijiro",
#           "OffGao"
#         ],
#         [
#           "マイクロブログ作ってみました（甘栗むいちゃいました的な感じで）。",
#           "@daijiro @tasukuchan 登録してみましたよー！"
#         ]
#       ]
#     ]
#   ]
# ]

「グニャラくん」がお気に入りに入れている2件のコメントがヒットしました。

  投稿時間でコメント検索

コメントの投稿時間で検索をします。Time型については data で扱っています。 この例では、指定した時間よりも前に投稿されているコメントを検索します。

実行例:

select Comments --filter 'last_modified<=1268802000' --output_columns posted_by.name,comment,last_modified --drilldown hash_tags,posted_by
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         5
#       ],
#       [
#         [
#           "posted_by.name",
#           "ShortText"
#         ],
#         [
#           "comment",
#           "ShortText"
#         ],
#         [
#           "last_modified",
#           "Time"
#         ]
#       ],
#       [
#         "hsiomaneki",
#         "マイクロブログ作ってみました（甘栗むいちゃいました的な感じで）。",
#         1268795100.0
#       ],
#       [
#         "グニャラくん",
#         "初の書き込み。テストテスト。",
#         1268794800.0
#       ],
#       [
#         "hsiomaneki",
#         "@tasukuchan ようこそ!!!",
#         1268795100.0
#       ],
#       [
#         "グニャラくん",
#         "@daijiro ありがとう！",
#         1268798400.0
#       ],
#       [
#         "グニャラくん",
#         "groongaなう #groonga",
#         1268802000.0
#       ]
#     ],
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "_nsubrecs",
#           "Int32"
#         ]
#       ],
#       [
#         "groonga",
#         1
#       ]
#     ],
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "_nsubrecs",
#           "Int32"
#         ]
#       ],
#       [
#         "daijiro",
#         2
#       ],
#       [
#         "tasukuchan",
#         3
#       ]
#     ]
#   ]
# ]

2010/03/17 14:00:00以前に書かれたコメント5件がヒットしました。また、ドリルダウンの結果も返ってきており、「hsiomaneki」が2件、「グニャラくん」が3件ヒットしていることがわかります。

  クエリ拡張

groongaでは、 /reference/commands/select コマンドにquery_expansionパラメータを指定することによって、ユーザが指定した検索文字列を適宜拡張することが可能です。

たとえば、ユーザが'シークヮーサー'という文字列で検索した場合に、'シークヮーサー OR シークァーサー'で検索した場合と同一の結果を返すことによって、本来ユーザが必要とする結果をよりもれなく検索できるようになります。

  準備

クエリ拡張機能を使用するためには、検索対象となる文書を格納するテーブル(ここでは文書テーブルと呼びます)以外に、ユーザの指定した検索文字列を置換するためのテーブル(ここでは置換テーブルと呼びます)を準備します。置換テーブルでは、その主キーが置換前の文字列となり、文字列型(ShortText)のカラムの値が置換後の文字列となります。

TODO: 文字列型のベクターカラムでも可能であり、その場合は各要素をORでつなげたものに置換されるということを記述する。

実際に文書テーブルと置換テーブルを作成してみましょう。

実行例:

table_create Doc TABLE_PAT_KEY ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Doc body COLUMN_SCALAR ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
table_create Term TABLE_PAT_KEY|KEY_NORMALIZE ShortText --default_tokenizer TokenBigram
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Term Doc_body COLUMN_INDEX|WITH_POSITION Doc body
# [[0, 1337566253.89858, 0.000355720520019531], true]
table_create Synonym TABLE_PAT_KEY ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Synonym body COLUMN_SCALAR ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
load --table Doc
[
{"_key": "001", "body": "すっぱいブドウと甘いシークァーサー"},
{"_key": "002", "body": "シークヮーサージュースとゴーヤチャンプル"},
]
# [[0, 1337566253.89858, 0.000355720520019531], 2]
load --table Synonym
[
{"_key": "シークァーサー", "body": "(シークァーサー OR シークヮーサー)"},
{"_key": "シークヮーサー", "body": "(シークァーサー OR シークヮーサー)"},
]
# [[0, 1337566253.89858, 0.000355720520019531], 2]

この例では、ユーザが"シークァーサー"と入力しても、"シークヮーサー"と入力しても、それぞれの異なる表記の文書をもれなく検索するための置換テーブルを作成しています。

  検索

それでは実際に、準備した置換テーブルを使ってみましょう。まずは、query_expansionパラメータを指定せずにselectコマンドを使って検索してみます。

実行例:

select Doc --match_columns body --query "シークァーサー"
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "body",
#           "ShortText"
#         ]
#       ],
#       [
#         1,
#         "001",
#         "すっぱいブドウと甘いシークァーサー"
#       ]
#     ]
#   ]
# ]
select Doc --match_columns body --query "シークヮーサー"
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "body",
#           "ShortText"
#         ]
#       ],
#       [
#         2,
#         "002",
#         "シークヮーサージュースとゴーヤチャンプル"
#       ]
#     ]
#   ]
# ]

指定された文字列に完全に一致するレコードのみがそれぞれヒットします。次に、query_expansionパラメータに、準備したSynonymテーブルのbodyカラムを指定してみましょう。

実行例:

select Doc --match_columns body --query "シークァーサー" --query_expansion Synonym.body
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "body",
#           "ShortText"
#         ]
#       ],
#       [
#         1,
#         "001",
#         "すっぱいブドウと甘いシークァーサー"
#       ],
#       [
#         2,
#         "002",
#         "シークヮーサージュースとゴーヤチャンプル"
#       ]
#     ]
#   ]
# ]
select Doc --match_columns body --query "シークヮーサー" --query_expansion Synonym.body
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "body",
#           "ShortText"
#         ]
#       ],
#       [
#         1,
#         "001",
#         "すっぱいブドウと甘いシークァーサー"
#       ],
#       [
#         2,
#         "002",
#         "シークヮーサージュースとゴーヤチャンプル"
#       ]
#     ]
#   ]
# ]

どちらのクエリ文字列も、"(シークァーサー OR シークヮーサー)"という文字列に置換されてから検索されるため、表記の揺れを吸収して検索できるようになりました。

サジェスト

groongaにはサジェスト機能があります。このセクションではこの機能の使い方とどのように動作しているかを説明します。

  はじめに

groongaのサジェスト機能は以下の機能を提供します。:

•   補完

•   補正

•   提案

  補完

補完はユーザの入力を支援します。ユーザが単語の一部分のみしか入力していないときに、登録済みの語の中から補完候補の語を返します。

例えば、以下が登録済みの語とします。:

•   "groonga"

•   "complete"

•   "correction"

•   "suggest"

    ユーザが"co"と入力したとき、"complete"と"correction"を補完候補として返します。これはどちらも"co"で始まっているからです。

    ユーザが"sug"と入力したとき、"suggest"を返します。これは"suggest"が"sug"から始まっているからです。

    ユーザが"ab"と入力したときは何も返しません。これは"ab"から始まる語が1つも登録されていないからです。

  補正

補正もユーザの入力を支援します。ユーザが間違った語を入力したときに登録済みの補正ペアの中から補正された語を返します。

例えば、以下のような補正ペアが登録されていたとします。
間違った語 | 正しい語
grroonga | groonga
gronga | groonga
gronnga | groonga

ユーザが"gronga"と入力したとき、"groonga"を返します。これは、"gronga"が「間違った語」にあり、対応する「正しい語」カラムの値が"groonga"だからです。

ユーザが"roonga"と入力したときは何も返しません。これは"roonga"が「間違った語」カラムにないからです。

  提案

提案は、たくさんの文書が見つかったときに、ユーザがさらに絞り込むことを支援します。ユーザがクエリを入力したとき、登録済みの関連クエリペアから追加のキーワードを選び、追加のキーワードを含んだ新しいクエリを返します。

例えば、以下の関連クエリペアが登録されているとします。:
キーワード | 関連クエリ
groonga | groonga search engine
search | Google search
speed | groonga speed

ユーザが"groonga"と入力したとき、"groonga search engine"を返します。これは、"groonga"が「キーワード」カラムの値にあり、対応する「関連クエリ」カラムの値が"groonga search engine"だからです。

ユーザが"MySQL"と入力したときは何も返しません。これは"MySQL"が「キーワード」カラムにないからです。

  学習

サジェスト機能を使う場合は、事前に登録済みのデータを用意する必要があります。これらのデータはユーザの入力を使って登録できます。これ用にgroonga-suggest-httpdコマンドとgroonga-suggest-learnerコマンドがあります。

  チュートリアル

TODO...

  補完

このセクションでは以下の補完機能について説明します。:

•   どのように動作するか

•   使い方

•   学習方法

  どのように動作するか

補完機能は補完される語を計算するために3種類の検索を使います。

1.  登録されている語を前方一致RK検索。

2.  学習したデータを共起検索。

3.  登録されている語を前方一致検索。（実行しないこともある）

  前方一致RK検索

RKはローマ字（Romaji）とカタカナ（Katakana）を意味しています。前方一致RK検索は登録されている語をユーザの入力から前方一致検索します。このとき、ユーザの入力はローマ字でもカタカナでもひらがなでも構いません。この機能は日本語を検索するときに便利です。

例えば、"日本"という語が登録されているとします。そして、その読みとして"ニホン"（カタカナにしないといけません）が登録されているとします。このとき、ユーザの入力が"ni"でも"二"でも"に"でも"日本"を見つけることができます。

  共起検索

共起検索は入力途中のユーザのクエリから登録されている語を見つけます。共起検索では検索データベースとしてユーザの入力シーケンスを使います。これはクエリログやアクセスログなどから学習します。

例えば、以下のようなユーザの入力シーケンスがあるとします。
入力 | 検索実行
s | していない
se | していない
sea | していない
sear | していない
searc | していない
search | した
e | していない
en | していない
eng | していない
engi | していない
engin | していない
engine | していない
enginen | していない（入力ミス！）
engine | した

groongaは以下のような補完ペアを作ります。:
入力 | 補完語
s | search
se | search
sea | search
sear | search
searc | search
e | engine
en | engine
eng | engine
engi | engine
engin | engine
engine | engine
enginen | engine

ユーザが検索を実行する前のすべての入力（例では"s"、"se"など）を検索を実行した語（例では"search"）に対応付けます。

厳密に言うとこの説明は正しくありません。なぜならタイムスタンプに関することを省略しているからです。groongaは本当は「ユーザが検索を実行する前のすべての入力を」使いません。厳密には「ユーザが検索を実行する前の1分以内の入力のみ」を使います。検索実行時から1分より前の入力は使われません。

ユーザが"sea"と入力したら、共起検索は"search"を返します。なぜなら、「入力」カラムには"sea"という値があり、対応する「補完語」カラムには"search"という値が入っているからです。

  前方一致検索

前方一致検索はユーザが入力した文字列から始まる登録済みの語を検索します。この検索は前方一致RK検索とは違ってローマ字、カタカナ、ひらがなを特別扱いしません。

この検索はいつも実行されるわけではありません。この検索は明示的に実行するように指示するか、前方一致RK検索と共起検索の両方がなにもヒットしないときのみ実行されます。

例えば、"search"が登録されているとします。ユーザは"s"、"se"、"sea"、"sear"、"searc"、"search"のどれでも"search"を補完候補として利用できます。

  使い方

groongaは補完機能を使うために /reference/commands/suggest コマンドを用意しています。 --type complete オプションを使うと補完機能を利用できます。

例えば、"en"と入力したときの補完結果を取得するコマンドは以下のようになります。:

実行例:

suggest --table item_query --column kana --types complete --frequency_threshold 1 --query en
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   {
#     "complete": [
#       [
#         1
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "_score",
#           "Int32"
#         ]
#       ],
#       [
#         "engine",
#         1
#       ]
#     ]
#   }
# ]

  学習方法

共起検索は学習データを使います。学習データはクエリログやアクセスログなどを元に作成します。学習データを作成するには、タイムスタンプ付きの入力シーケンスと、タイムスタンプ付きの検索実行時の入力内容が必要です。

例えば、ユーザが"engine"で検索したいとします。ユーザが以下のようなシーケンスで検索クエリを入力したとします。:

1.  2011-08-10T13:33:23+09:00: e

2.  2011-08-10T13:33:23+09:00: en

3.  2011-08-10T13:33:24+09:00: eng

4.  2011-08-10T13:33:24+09:00: engi

5.  2011-08-10T13:33:24+09:00: engin

6.  2011-08-10T13:33:25+09:00: engine （検索実行！）

    以下のコマンドでこの入力シーケンスから学習できます。:

    load --table event_query --each 'suggest_preparer(_id, type, item, sequence, time, pair_query)'
    [
    {"sequence": "1", "time": 1312950803.86057, "item": "e"},
    {"sequence": "1", "time": 1312950803.96857, "item": "en"},
    {"sequence": "1", "time": 1312950804.26057, "item": "eng"},
    {"sequence": "1", "time": 1312950804.56057, "item": "engi"},
    {"sequence": "1", "time": 1312950804.76057, "item": "engin"},
    {"sequence": "1", "time": 1312950805.86057, "item": "engine", "type": "submit"}
    ]

  補正

このセクションでは以下の補正機能について説明します。:

•   どのように動作するか

•   使い方

•   学習方法

  どのように動作するか

補正機能は補正した語を計算するために3種類の検索を使います。:

1.  学習したデータを共起検索。

2.  登録されている語を類似検索。（実行しないこともある）

  共起検索

共起検索はユーザの間違って入力した文字列から登録済みの語を検索します。共起検索ではユーザがどのように検索を実行したかを使います。ユーザがどのように検索したかはクエリログやアクセスログから学習します。

例えば、ユーザが以下のように検索を実行したとします。:
クエリ | 時刻
serach （入力ミス！） | 2011-08-10T22:20:50+09:00
search （修正！） | 2011-08-10T22:20:52+09:00

上記の検索実行ログから以下のような補正ペアを作ります。
入力 | 補正された語
serach | search

1分以内の連続して実行された検索をユーザが入力を補正したものとみなします。検索を実行した間の入力途中の入力シーケンスは、補正用の学習データとしては利用しません。

ユーザが"serach"と入力した場合、共起検索は"saerch"を返します。なぜなら、"serach"が「入力」カラムにあり、対応する「補正される語」カラムの値が"search"だからです。

  類似検索

類似検索はユーザの入力をトークナイズし、同じトークンを含んだ登録済みの語を検索します。トークナイズにはTokenBigramトークナイザーを使います。これは /reference/executables/groonga-suggest-create-dataset が作るサジェストデータセットスキーマではデフォルトトークナイザーとしてTokenBigramトークナイザーを使っているからです。

例えば、"search engine"という語が登録されているとします。ユーザが"web search service"や"sound engine"などで検索すると"search engine"が補正候補になります。なぜなら、"search engine"と"web search engine"は"search"という同じトークンを持つからです。また、"search engine"と"sound engine"は"engine"という同じトークンを持っています。

"search engine"は"search"トークンと"engine"トークンにトークナイズされます。（groongaのTokenBigramトークナイザーは連続するアルファベットと数字を2文字にトークナイズしません。これは検索ノイズを減らす為です。確実に2文字でトークナイズするためにはTokenBigramSplitSymbolAlphaDigitを使います。）"web search service"は"web"トークンと"search"トークンと"service"トークンにトークナイズされます。"sound engine"は"sound"トークンと"engine"トークンにトークナイズされます。

  使い方

groongaは補正機能を使うために /reference/commands/suggest コマンドを用意しています。 --type correct オプションを使うと補正機能を利用できます。

例えば、"saerch"と入力した時の補正結果取得するコマンドは以下のようになります。:

実行例:

suggest --table item_query --column kana --types correction --frequency_threshold 1 --query saerch
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   {
#     "correct": [
#       [
#         1
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "_score",
#           "Int32"
#         ]
#       ],
#       [
#         "search",
#         1
#       ]
#     ]
#   }
# ]

  学習方法

共起検索は学習データを使います。学習データはクエリログやアクセスログから作ります。学習データを作るためにはユーザが検索を実行したときの検索クエリとタイムスタンプが必要です。

例えば、ユーザが"search"で検索したかったとします。しかし、ユーザは正しい"search"というクエリで検索を実行する前に間違って"saerch"で検索してしまいました。このユーザの入力シーケンスは以下のようになります。:

1.  2011-08-10T13:33:23+09:00: s

2.  2011-08-10T13:33:23+09:00: sa

3.  2011-08-10T13:33:24+09:00: sae

4.  2011-08-10T13:33:24+09:00: saer

5.  2011-08-10T13:33:24+09:00: saerc

6.  2011-08-10T13:33:25+09:00: saerch （検索実行！）

7.  2011-08-10T13:33:29+09:00: serch （修正中…）

8.  2011-08-10T13:33:30+09:00: search （検索実行！）

    以下のコマンドでこの入力シーケンスから学習できます。:

    load --table event_query --each 'suggest_preparer(_id, type, item, sequence, time, pair_query)'
    [
    {"sequence": "1", "time": 1312950803.86057, "item": "s"},
    {"sequence": "1", "time": 1312950803.96857, "item": "sa"},
    {"sequence": "1", "time": 1312950804.26057, "item": "sae"},
    {"sequence": "1", "time": 1312950804.56057, "item": "saer"},
    {"sequence": "1", "time": 1312950804.76057, "item": "saerc"},
    {"sequence": "1", "time": 1312950805.76057, "item": "saerch", "type": "submit"},
    {"sequence": "1", "time": 1312950809.76057, "item": "serch"},
    {"sequence": "1", "time": 1312950810.86057, "item": "search", "type": "submit"}
    ]

  提案

このセクションでは以下の補完機能について説明します。:

•   どのように動作するか

•   使い方

•   学習方法

  どのように動作するか

提案機能は提案する語を計算するために1種類の検索を使います。:

1.  学習したデータを共起検索。

  共起検索

共起検索はユーザの入力と関連する語を検索します。共起検索ではユーザの実行したときの検索クエリを使います。このデータはクエリログやアクセスログなどから学習します。

例えば、ユーザが以下のように検索を実行したとします。:
クエリ
search engine
web search realtime

groongaは以下のような提案ペアを作成します。
入力 | 提案される語
search | search engine
engine | search engine
web | web search realtime
search | web search realtime
realtime | web search realtime

これらのペアは以下の手順で作成します。:

1.  ユーザの入力をTokenDelimitトークナイザーでトークナイズします。TokenDelimitは空白をトークンの区切りに使います。（例えば、"search engine"は"search"トークンと"engine"トークンの2つのトークンにトークナイズされます。）

2.  各トークンについて、トークンと元のクエリからなるペアを作成する。

    ユーザが"search"と入力したとき、共起検索は"search engine"と"web search raltime"を返します。これは、"search"が2つの「入力」カラムに含まれていて、対応するそれぞれの「提案される語」カラムの値が"search engine"と"web search realtime"だからです。

  使い方

groongaは提案機能を使うために /reference/commands/suggest コマンドを用意しています。 --type suggest オプションを使うと提案機能を利用できます。

例えば、"search"と入力した時の提案結果を取得するコマンドは以下の通りです。:

実行例:

suggest --table item_query --column kana --types suggest --frequency_threshold 1 --query search
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   {
#     "suggest": [
#       [
#         2
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "_score",
#           "Int32"
#         ]
#       ],
#       [
#         "search engine",
#         1
#       ],
#       [
#         "web search realtime",
#         1
#       ]
#     ]
#   }
# ]

  学習方法

共起検索は学習データを使います。学習データはクエリログやアクセスログなどを元に作成します。学習データを作成するには、タイムスタンプ付きの入力シーケンスと、タイムスタンプ付きの検索実行時の入力内容が必要です。

例えば、ユーザが"engine"で検索したいとします。ユーザが以下のようなシーケンスで検索クエリを入力したとします。:

1.  2011-08-10T13:33:25+09:00: search engine （検索実行）

2.  2011-08-10T13:33:28+09:00: web search realtime （検索実行）

    以下のコマンドで上記の検索実行結果から学習します。:

    load --table event_query --each 'suggest_preparer(_id, type, item, sequence, time, pair_query)'
    [
    {"sequence": "1", "time": 1312950803.86057, "item": "search engine", "type": "submit"},
    {"sequence": "1", "time": 1312950808.86057, "item": "web search realtime", "type": "submit"}
    ]

位置情報検索

groongaは位置情報検索をサポートしています。検索にはインデックスを使うので全文検索と同様に位置情報も高速に検索できます。

  対応している機能

groongaは位置情報データのうち座標データのみサポートしています。線や面などはサポートしています。よってgroongaができることは以下の通りです。

1.  カラムに座標データを保存できる。

2.  指定した四角形の中にある座標を持つレコードを検索できる。

3.  指定した円の中にある座標を持つレコードを検索できる。

4.  2点間の距離を計算できる。

5.  指定した座標からの距離が近い順にレコードをソートできる。

    以下はgroongaの位置情報検索を利用例です。

•   駅の近くにあるマクドナルドをリストする。

•   現在地から近い順にケンタッキーをソートし、現在地からの距離付きでリストする。

    以下はgroongaではできないことです。

•   市内にあるマクドナルドを検索する。（groongaは四角形と円以外の形状の位置情報検索をサポートしていません。）

•   湖を表すレコードに位置情報として座標ではなく範囲を格納する。（カラムには座標データ以外を格納できません。）

    以下の図はgroongaの位置情報検索機能を示しています。

    以下の図はレコードのみがある図です。黒い点がレコードを表しています。以降の図ではレコードがどのように扱われるかを示します。 [image: only records] [画像]

    執筆中。。。 （ 下書き ）

サーバー

  サーバーパッケージ

groonga パッケージは全文検索を行うための最小構成のパッケージです。サーバー用途で使うために、設定済みのパッケージを追加でインストールすることができます。

サーバー用途の3つのパッケージがあります。

•   groonga-httpd (nginxをベースにしたHTTPサーバー)

•   groonga-server-http (簡易HTTPサーバー)

•   groonga-server-gqtp (GQTPサーバー)

    groonga-httpd と groonga-server-http パッケージは使用ポートが一緒なので衝突します。どちらのパッケージを使うのがいいのかは /server/http/comparison を参照してください。

  groonga-httpd

groonga-httpd はnginxをベースにしたHTTPサーバーパッケージです。

設定済みの内容:
項目 | 既定値
ポート番号 | 10041
アクセスログ | /var/log/groonga/httpd/acccess.log
エラーログ | /var/log/groonga/http-query.log
データベース | /var/lib/groonga/db/*
設定ファイル | /etc/groonga/httpd/groonga-httpd.conf

  HTTPサーバーを起動

groonga HTTPサーバーを起動(Debian/Ubuntu/CentOS):

% sudo service groonga-httpd start

groonga HTTPサーバーを起動(Fedora):

% sudo systemctl start groonga-httpd

  HTTPサーバーを終了

groonga HTTPサーバーを終了(Debian/Ubuntu/CentOS):

% sudo service groonga-httpd stop

groonga HTTPサーバーを起動(Fedora):

% sudo systemctl stop groonga-httpd

  HTTPサーバーを再起動

groonga HTTPサーバーを再起動(Debian/Ubuntu/CentOS):

% sudo service groonga-httpd restart

groonga HTTPサーバーを再起動(Fedora):

% sudo systemctl restart groonga-httpd

  groonga-server-http

groonga-server-http は簡易HTTPサーバーパッケージです。

設定済みの内容:
項目 | 既定値
ポート番号 | 10041
process-log | /var/log/groonga/groonga-http.log
query-log | /var/log/groonga/http-query.log
データベース | /var/lib/groonga/db/*

サーバー設定ファイル (Debian/Ubuntu):

/etc/default/groonga/groonga-server-http

サーバー設定ファイル(CentOS):

/etc/sysconfig/groonga-server-http

  HTTPサーバーを起動

groonga HTTPサーバーを起動(Debian/Ubuntu/CentOS):

% sudo service groonga-server-http start

groonga HTTPサーバーを起動(Fedora):

% sudo systemctl start groonga-server-http

  HTTPサーバーを終了

groonga HTTPサーバーを終了(Debian/Ubuntu/CentOS):

% sudo service groonga-server-http stop

groonga GQTPサーバーを終了(Fedora):

% sudo systemctl stop groonga-server-http

  HTTPサーバーを再起動

groonga HTTPサーバーを再起動(Debian/Ubuntu/CentOS):

% sudo service groonga-server-http restart

groonga HTTPサーバーを再起動(Fedora):

% sudo systemctl restart groonga-server-http

  groonga-server-gqtp

groonga-server-gqtp はGQTPサーバーパッケージです。
項目 | 既定値
ポート番号 | 10043
process-log | /var/log/groonga/groonga-gqtp.log
query-log | /var/log/groonga/gqtp-query.log
データベース | /var/lib/groonga/db/*

サーバー設定ファイル (Debian/Ubuntu):

/etc/default/groonga/groonga-server-gqtp

サーバー設定ファイル(CentOS):

/etc/sysconfig/groonga-server-gqtp

  GQTPサーバーを起動

groonga GQTPサーバーを起動(Debian/Ubuntu/CentOS):

% sudo service groonga-server-gqtp start

groonga GQTPサーバーを起動(Fedora):

% sudo systemctl start groonga-server-gqtp

  GQTPサーバーを終了

groonga GQTPサーバーを終了(Debian/Ubuntu/CentOS):

% sudo service groonga-server-http stop

groonga GQTPサーバーを終了(Fedora):

% sudo systemctl stop groonga-server-gqtp

  GQTPサーバーを再起動

groonga HTTPサーバーを再起動(Debian/Ubuntu/CentOS):

% sudo service groonga-server-gqtp restart

groonga HTTPサーバーを再起動(Fedora):

% sudo systemctl restart groonga-server-gqtp

  GQTP

TODO

/reference/executables/groonga を参照してください。

  HTTP

groongaは2つのHTTPサーバー実装を提供しています。

•   http/groonga

•   http/groonga-httpd

    http/groonga はシンプルな実装です。高速に動作しますがHTTPの機能の多くは実装されていません。 http/groonga はコマンドラインをいくつか指定するだけで動くのでgroongaを簡単に試すことができます。

    http/groonga-httpd は nginx をベースにした実装です。 http/groonga-httpd も高速に動作し、しかも多くのHTTPの機能を使えます。

ノート http/groonga-httpd はまだ実験的な扱いです。

  比較

groonga と groonga-httpd にはたくさんの違いがあります。以下はそれらの違いを示す比較表です。
 | groonga | groonga-httpd
性能 | ○ | ○
複数CPUコア対応 | ○（マルチスレッドで対応） | ○（マルチプロセスで対応）
設定ファイル | なくてもよい | 必須
プレフィックスパスの変更 | × | ○
コマンドバージョンの変更 | ○ | ×（まもなく実装予定）
複数データベース | × | ○
認証 | × | ○
gzip圧縮 | × | ○
POST | × | ○
HTTPS | × | ○
アクセスログ | × | ○
ダウンタイムなしでのアップグレード | × | ○

  性能

groonga と groonga-httpd はどちらも非常に高速です。どちらも同じスループットで動きます。

  複数CPUコア対応

groongaは複数のCPUコアを使って性能を向上できます。 groonga はマルチスレッドを使って性能を向上させます。 groonga-httpd はマルチプロセスを使って性能を向上させます。

groonga はデフォルトでCPUコアと同じ数のスレッドを使います。もし、CPUコアが8個あった場合は、デフォルトで8個のスレッドを使います。

groonga-httpd はデフォルトで1つのプロセスを使います。複数のCPUコアを使う場合は worker_processes ディレクティブを設定する必要があります。CPUコアが8個ある場合は、以下のように設定ファイルに worker_processes 8 と指定します。:

worker_processes 8;
http {
  # ...
}

  設定ファイル

groonga は設定ファイルがなくても動きます。ポート番号や最大スレッド数などといった設定項目はすべてコマンドラインから指定できます。設定ファイルを使っても設定項目を指定することができます。

groonga はいくつかのオプションを指定するだけで実行できるので、非常に簡単にgroonga用のHTTPサーバーを起動することができます。以下は groonga でHTTPサーバーを起動する一番簡単なコマンドラインです。:

% groonga --protocol http -d /PATH/TO/DATABASE

groonga-httpd を実行するには設定ファイルが必須です。以下は groonga-httpd でHTTPサーバーを実行する一番簡単な設定ファイルです。:

events {
}
http {
  server {
    listen 10041;
    location /d/ {
      groonga on;
      groonga_database /PATH/TO/DATABASE;
    }
  }
}

  プレフィックスパスの変更

groonga は /d/ から始まるパスをコマンドURLとして受け付けます。例えば、 http://localhost:10041/d/status となります。この /d/ というプレフィックスパスを変更することはできません。

groonga-httpd はプレフィックスパスを変更することができます。例えば、 http://localhost:10041/api/status というコマンドURLを使うことができます。以下は /api/ をプレフィックスパスとして使う設定例です。:

events {
}
http {
  server {
    listen 10041;
    location /api/ { # <- change this
      groonga on;
      groonga_database /PATH/TO/DATABASE;
    }
  }
}

  コマンドバージョンの変更

groongaには /reference/command/command_version という仕組みがあります。これは後方互換性を維持したままgroongaコマンドをアップグレードするための仕組みです。

groonga は --default-command-version オプションでデフォルトのコマンドバージョンを変更できます。以下はデフォルトのコマンドバージョンとしてコマンドバージョン2を使うコマンドライン例です。:

% groonga --protocol http --default-command-version 2 -d /PATH/TO/DATABASE

groonga-httpd はまだデフォルトのコマンドバージョンを変更できません。しかし、すぐにサポートする予定です。サポートされたら、同じ groonga-httpd プロセス内で異なったコマンドバージョンのgroongaコマンドを提供できます。以下はコマンドバージョン1のコマンドを /api/1/ 以下で、コマンドバージョン2のコマンドを /api/2/ 以下で提供するための設定例です。:

events {
}
http {
  server {
    listen 10041;
    groonga_database /PATH/TO/DATABASE;
    location /api/1/ {
      groonga on;
      groogna_default_command_version 1;
    }
    location /api/2/ {
      groonga on;
      groogna_default_command_version 2;
    }
  }
}

  複数データベース

groonga は1つのプロセスで1つのデータベースしか使うことができません。

groonga-httpd は同一プロセス内で複数のデータベースを使うことができます。以下は /tmp/db1 にあるデータベースを /db1/ 以下で、 /tmp/db2 にあるデータベースを /db2/ 以下で提供する設定例です。:

events {
}
http {
  server {
    listen 10041;
    location /db1/ {
      groonga on;
      groonga_database /tmp/db1;
    }
    location /db2/ {
      groonga on;
      groonga_database /tmp/db2;
    }
  }
}

  認証

HTTPではベーシック認証やダイジェスト認証などの認証方法をサポートしています。認証することにより /reference/commands/shutdown などのように危険なコマンドの実行を制限することができます。

groonga では認証できません。危険なコマンドの使用を制限するためには、iptablesやリバースプロキシなど他のツールを使う必要があります。

groonga-httpd はベーシック認証をサポートしています。以下は /reference/commands/shutdown コマンドの使用を制限する設定例です。:

events {
}
http {
  server {
    listen 10041;
    groonga_database /PATH/TO/DATABASE;
    location /d/shutdown {
      groonga on;
      auth_basic           "manager is required!";
      auth_basic_user_file "/etc/managers.htpasswd";
    }
    location /d/ {
      groonga on;
    }
  }
}

  gzip圧縮

HTTPは Content-Encoding: gzip レスポンスヘッダーを付けてgzipでレスポンスを圧縮する機能をサポートしています。これはネットワーク流量を小さくすることができます。大きな検索結果を返すときに有用です。

groonga は圧縮をサポートしていません。圧縮をサポートするためには、リバースプロキシを使う必要があります。

groonga-httpd はgzip圧縮をサポートしています。以下はレスポンスをgzipで圧縮する設定例です。:

events {
}
http {
  server {
    listen 10041;
    groonga_database /PATH/TO/DATABASE;
    location /d/ {
      groonga    on;
      gzip       on;
      gzip_types *;
    }
  }
}

gzip_types * を指定していることに注意してください。この設定はとても重要な設定です。 gzip_types はgzip対象のデータフォーマットをMIMEタイプで指定します。 groonga-httpd は JSON、XML、MessagePackのどれかのフォーマットでデータを返します。しかし、これらのフォーマットは gzip_types のデフォルト値に含まれていません。 gzip_types のデフォルト値は text/html です。

groonga-httpd のレスポンスデータをgzip圧縮するには、明示的に gzip_types * または gzip_types application/json text/xml application/x-msgpack と指定する必要があります。 gzip_types * の方がおすすめです。理由は2つあります。1つは、groongaが、将来、他のフォーマットもサポートする可能性もあるからという理由です。2つめは、この location のすべてのリクエストはgroongaが処理するので、他のモジュールのことについて考えなくてもよいからという理由です。

  POST

JSONデータをPOSTすることでデータをロードすることができます。POSTでロードする場合は以下のルールに従ってください。

•   Content-Type ヘッダーの値を application/json にする。

•   JSONデータはbodyとして送る。

•   テーブル名は table=名前 というようにクエリーパラメーターで指定する。

    以下はcurlを使って alice と bob という2人のユーザーを Users テーブルにロードするコマンドラインの例です:

    % curl --data-binary '[{"_key": "alice"}, {"_key": "bob"}]' -H "Content-Type: application/json" "http://localhost:10041/d/load?table=Users"

  HTTPS

TODO

  アクセスログ

TODO

  ダウンタイムなしでのアップグレード

TODO

  groonga

TODO

  groonga-httpd

TODO

リファレンスマニュアル

  実行ファイル

groongaパッケージが提供する実行ファイルについて説明します。

  grnslap

  名前

grnslap - groongaプロセスの通信層のパフォーマンスをチェックするツール

  書式

grnslap [options] [dest]

  説明

grnslapは、groongaプロセスに対してリクエストを多重に行い、パフォーマンスをチェックするためのツールです。

groonga独自プロトコルであるgqtpと、httpの両プロトコルでリクエストを行うことができます。また、リクエストの多重度を指定することができます。

クエリの内容を標準入力から与えることができます。実稼動環境でのクエリパタンに近いクエリを標準入力に与えることによって、実稼動環境に近い状態での検証を行うことができます。

現在は、make installしてもインストールは行われない。

  オプション

-P  リクエストのプロトコルを指定します。

    http httpでリクエストします。対象のhttpのパス群(GETパラメータを含む)をLF区切り形式で標準入力に与えると、それらのパスに順次アクセスします。

    gqtp gqtpでリクエストします。gqtpのリクエストをLF区切り形式で標準入力に与えると、それらのリクエストを順次行います。

-m  リクエストの多重度を指定します。初期値は10です。

  引数

dest
    接続先のホスト名とポート番号をを指定します(デフォルト値は'localhost:10041')。ポート番号を指定しない場合には、10041が指定されたものとします。

  サンプル

http://localhost:10041/d/status に、多重度100でリクエストを行う。

> yes /d/status | head -n 100 | grnslap -P http -m 100 localhost:10041
2009-11-12 19:34:09.998696|begin: max_concurrency=100 max_tp=10000
2009-11-12 19:34:10.011208|end  : n=100 min=46 max=382 avg=0 qps=7992.966190 etime=0.012511

  grntest

  名前

grntest - groongaテストプログラム

  書式

grntest  [options...] [script] [db]

  説明

grntestは、groonga汎用テストツールです。

groongaを単独のプロセスとして利用する場合はもちろん、サーバプログラムとして利用する場合の動作確認や実行速度測定が可能です。

grntest用のデータファイルは自分で作成することも既存のものを利用することもできます。既存のデータファイルは、ftp.groonga.orgから必要に応じダウンロードします。そのため、groonga及びgrntestが動作し、インターネットに接続できる環境であればgroongaコマンドの知識がなくてもgroongaの動作を確認できます。

現在は、Linux 及びWindows上で動作します。make installしてもインストールは行われません。

  オプション

-i, --host <ip/hostname>
    接続するgroongaサーバを、ipアドレスまたはホスト名で指定します。指定先にgroongaサーバが立ち上がっていない場合、接続不能となることに注意してください。このオプションを指定しない場合、grntestは自動的にlocalhostのgroongaサーバを起動して接続します。

-p, --port <port number>
    自動的に起動するgroongaサーバ、または明示的に指定した接続先のgroonga サーバが利用するポート番号を指定します。接続先のgroongaサーバが利用しているポートと、このオプションで指定したポート番号が異なる場合、接続不能となることに注意してください。

--dir
    ftp.groonga.org に用意されているスクリプトファイルを表示します。

--ftp
    ftp.groonga.orgとFTP通信を行い、scriptファイルの同期やログファイルの送信を行います。

--log-output-dir
    デフォルトでは、grntest終了後のログファイルの出力先ははカレントディレクトリです。このオプションを利用すると、任意のディレクトリに出力先を変更することができます。

--groonga <groonga_path>
    groongaコマンドのパスを指定します。デフォルトでは、PATHの中からgroongaコマンドを探します。

--protocol <gqtp|http>
    groongaコマンドが使うプロトコルとして gqtp または http を指定します。

  引数

script
    grntestの動作方法(以下、grntest命令と呼びます)を記述したテキストファイルです。拡張子は.scrです。

db  grntestが利用するgroonga データベースです。指定されたデータベースが存在しない場合、grntestが新規に作成します。またgroonga サーバを自動的に起動する場合もこの引数で指定したデータベースが利用されます。接続するgroonga サーバを明示的に指定した場合に利用するデータベースは、接続先サーバが使用中のデータベースになることに注意してください。

  使い方

まず、シェル上(Windowsならコマンドプロンプト上)で:

grntest test.scr 任意のDB名

とタイプしてください。もしgrntestが正常に動作すれば、:

test-ユーザ名-数字.log

というファイルが作成されるはずです。作成されない場合、このドキュメントの「トラブルシューティング」の章を参照してください。

  スクリプトファイル

スクリプトファイルは、grntest命令を記述したテキストファイルです。 ";"セミコロンを利用して、一行に複数のgrntest命令を記述することができます。一行に複数のgrntest命令がある場合、各命令は並列に実行されます。 "#"で始まる行はコメントとして扱われます。

  grntest命令

現在サポートされているgrntest命令は以下の8つです。 do_local コマンドファイル [スレッド数] [繰り返し数] コマンドファイルをgrntest単体で実行します。スレッド数が指定されている場合、複数のスレッドで同じコマンドファイルを同時に実行します。繰り返し数が指定されてい場合、コマンドファイルの内容を繰り返し実行します。スレッド数、繰り返し数とも省略時は1です。1スレッドで複数回動作させたい場合は、do_local コマンドファイル 1 [繰り返し数]と明示的に指定してください。

do_gqpt コマンドファイル [スレッド数] [繰り返し数] コマンドファイルをgroongaサーバで実行します。スレッド数や繰り返し数の意味はdo_localの場合と同じです。

rep_local コマンドファイル [スレッド数] [繰り返し数] コマンドファイルをgrntest単体で実行し、より詳細な報告を行います。

rep_gqpt コマンドファイル [スレッド数] [繰り返し数] コマンドファイルをgroongaサーバで実行し、より詳細な報告を行います。 スレッド数や繰り返し数の意味はdo_localと 同じです。

out_local コマンドファイル 入力ファイル名 コマンドファイルをgrntest単体で実行し、各コマンドの実行結果をすべて”出力ファイル"に書きだします。この結果は、test_local,　test_gqtp命令で利用します。なおこの命令の「出力ファイル」とは、grntest実行時に自動的に作成されるログとは別のものです。grntestではコメントが利用できる以外、:

groonga < コマンドファイル > 出力ファイル

とした場合と同じです。

out_gqtp コマンドファイル 出力ファイル名 コマンドファイルをgroongaサーバで実行します。その他はout_local命令と同等です。

test_local コマンドファイル 入力ファイル名
    コマンドファイルをgrntest単体で実行し、各コマンドの実行結果を入力ファイルと比較します。処理時間など本質的要素以外に差分があった場合、差分を、入力ファイル.diffというファイルに書きだします。

  コマンドファイル

コマンドファイルは、groonga組み込みコマンドを1行に1つずつ記述したテキストファイルです。拡張子に制限はありません。groonga組み込みコマンドに関しては /reference/command を参照してください。

  サンプル

スクリプトファイルのサンプルです。:

# sample script
rep_local test.ddl
do_local test.load;
do_gqtp test.select 10 10; do_local test.status 10

上記の意味は以下のとおりです。

1行目 コメント行。

2行目 test.dll というコマンドファイルをgroonga単体で実行し、詳細に報告する。

3行目 test.load というコマンドファイルをgroonga単体で実行する。(最後の";"セミコロンは複数のgrntest命令を記述する場合に必要ですが、この例のように1つのgrntest命令を実行する場合に付与しても問題ありません。)

4行目 test.select というコマンドファイルをgroongaサーバで10個のスレッドで同時に実行する。各スレッドはtest.selectの中身を10回繰り返す。また同時に、groonga単体でtest.statusというコマンドファイルを10個のスレッドで実行する。

  特殊命令

スクリプトファイルのコメント行には特殊コマンドを埋め込むことが可能です。現在サポートされている特殊命令は以下の二つです。

#SET_HOST <ip/hostname>
    -i, --hostオプションと同等の機能です。コマンドラインオプションに指定したIPアドレス/ホスト名と、SET_HOSTで指定したIPアドレス/ホスト名が異なる場合、またコマンドラインオプションを指定しなかった場合にもSET_HOSTが優先されます。SET_HOSTを利用した場合、サーバが自動的には起動されないのもコマンドラインオプションで指定した場合と同様です。

#SET_PORT <port number>
    -p, --port オプションと同等の機能です。コマンドラインオプションに指定したポート番号とSET_PORTで指定したポート番号が異なる場合、またコマンドラインオプションを指定しなかった場合にもSET_PORTが優先されます。

    特殊命令はスクリプトファイルの任意の場所に書き込むことができます。同一ファイル内に複数回特殊命令を記述した場合、「最後の」特殊命令が有効となります。

    例えば、

    $ ./grntest --port 20010 test.scr testdb

    とコマンド上でポートを指定した場合でも、もしtest.scrの中身が

    #SET_PORT 10900
    rep_local test.ddl
    do_local test.load;
    rep_gqtp test.select 10 10; rep_local test.status 10
    #SET_PORT 10400

    であれば、自動的に起動されるgroongaサーバはポート番号10400を利用します。

  grntest実行結果

grntestが正常に終了すると、(拡張子を除いた)スクリプト名-ユーザ名-実行開始時刻.logという形式のログファイルがカレントディレクトリに作られます。ログファイルは自動的にftp.groonga.org に送信されます。ログファイルは以下のようなjson形式のテキストです。

[{"script": "test.scr",
  "user": "homepage",
  "date": "2010-04-14 22:47:04",
  "CPU": Intel(R) Pentium(R) 4 CPU 2.80GHz",
  "BIT": 32,
  "CORE": 1,
  "RAM": "975MBytes",
  "HDD": "257662232KBytes",
  "OS": "Linux 2.4.20-24.7-i686",
  "HOST": "localhost",
  "PORT": "10041",
  "VERSION": "0.1.8-100-ga54c5f8"
},
{"jobs": "rep_local test.ddl",
"detail": [
[0, "table_create res_table --key_type ShortText", 1490, 3086, [0,1271252824.25846,0.00144
7]],
[0, "column_create res_table res_column --type Text", 3137, 5956, [0,1271252824.2601,0.002
741]],
[0, "column_create res_table user_column --type Text", 6020, 8935, [0,1271252824.26298,0.0
02841]],
[0, "column_create res_table mail_column --type Text", 8990, 11925, [0,1271252824.26595,0.
002861]],
[0, "column_create res_table time_column --type Time", 12008, 13192, [0,1271252824.26897,0
.001147]],
[0, "status", 13214, 13277, [0,1271252824.27018,3.0e-05]],
[0, "table_create thread_table --key_type ShortText", 13289, 14541, [0,1271252824.27025,0.
001213]],
[0, "column_create thread_table thread_title_column --type ShortText", 14570, 17380, [0,12
71252824.27153,0.002741]],
[0, "status", 17435, 17480, [0,1271252824.2744,2.7e-05]],
[0, "table_create lexicon_table --flags 129 --key_type ShortText --default_tokenizer Token
Bigram", 17491, 18970, [0,1271252824.27446,0.001431]],
[0, "column_create lexicon_table inv_res_column 514 res_table res_column ", 18998, 33248,
[0,1271252824.27596,0.01418]],
[0, "column_create lexicon_table inv_thread_column 514 thread_table thread_title_column ",
 33285, 48472, [0,1271252824.29025,0.015119]],
[0, "status", 48509, 48554, [0,1271252824.30547,2.7e-05]]],
"summary" :[{"job": "rep_local test.ddl", "latency": 48607, "self": 47719, "qps": 272.4281
73, "min": 45, "max": 15187, "queries": 13}]},
{"jobs": "do_local test.load; ",
"summary" :[{"job": "do_local test.load", "latency": 68693, "self": 19801, "qps": 1010.049
997, "min": 202, "max": 5453, "queries": 20}]},
{"jobs": "do_gqtp test.select 10 10; do_local test.status 10",
"summary" :[{"job": " do_local test.status 10", "latency": 805990, "self": 737014, "qps":
54.273053, "min": 24, "max": 218, "queries": 40},{"job": "do_gqtp test.select 10 10", "lat
ency": 831495, "self": 762519, "qps": 1967.164097, "min": 73, "max": 135631, "queries": 15
00}]},
{"total": 915408, "qps": 1718.359464, "queries": 1573}]

  制限事項

•   スクリプトファイルの一行には複数のgrntest命令を記述できますが、すべてのスレッド数の合計は最大64までに制限されます。

•   コマンドファイル中のgroongaコマンドの長さは最長5000000byteです。

  トラブルシューティング

もし、grntestが正常に動作しない場合、まず以下を確認してください。

•   インターネットに接続しているか？ --ftp オプションを指定すると、grntestは動作のたびにftp.groonga.orgと通信します。ftp.groonga.orgと通信可能でない場合、grntestは正常に動作しません。

•   groonga サーバが動作していないか？　grntestは、-i, --host オプションで明示的にサーバを指定しないかぎり、自動的にlocalhostのgroongaサーバを立ち上げます。すでにgroongaサーバが動作している場合、grntestは正常に動作しない可能性があります。

•   指定したDBが適切か？ grntestは、引数で指定したDBの中身はチェックしません。もし指定されたDBが存在しなければ自動的にDBを作成しますが、もしファイルとして存在する場合は中身に関わらず動作を続けてしまい、結果が異常になる可能性があります。

    以上の原因でなければ、問題はgrntestかgroongaにあります。ご報告をお願いします。

  groongaコマンド

  名前

groonga - 列指向データベース機能を持つ全文検索エンジンソフトウェア

  書式

groonga [options] [dest] [command [args]]

  説明

groongaは列指向のデータベース機能を持つ高速でスケーラブルな全文検索エンジンです。 groongaのデータベースは、groongaコマンドかCライブラリインタフェースを通して操作することができます。このマニュアルページでは、groongaコマンドの使い方について説明します。

  オプション

-n  新たなデータベースを作成します。

-c  クライアントモードで実行します。

-s  サーバモードで実行します。

-d  デーモンモードで実行します。(forkする点がサーバモードと異なる)

-e, --encoding <encoding>
    データベースで使用する文字エンコーディング方式を指定します。新たなデータベースを作成する時のみ有効です。none, euc, utf8, sjis, latin, koi8rのいずれかが指定できます。

-l, --log-level <log level>
    ログレベルを指定します。0〜8までの数値が指定可能で、数が大きいほど多くのログが出力されます。

-a, --address <ip/hostname>
    バージョン 1.2.2 で撤廃: Use --bind-address instead.

--bind-address <ip/hostname>
    バージョン 1.2.2 で追加.

    サーバモードかデーモンモードで実行するとき、listenするアドレスを指定します。(デフォルトは hostname の返すホスト名)

-p, --port <port number>
    クライアント、サーバ、またはデーモンモードで使用するTCPポート番号。 (デフォルトは10041番)

-i, --server-id <ip/hostname>
    サーバモードかデーモンモードで実行するとき、サーバのIDとなるアドレスを指定します。(デフォルトは`hostname`の返すホスト名)

-h, --help
    ヘルプメッセージを出力します。

--document-root <path>
    httpサーバとしてgroongaを使用する場合に静的ページを格納するディレクトリを指定します。

    デフォルトでは、データベースを管理するための汎用的なページに対応するファイルが/usr/share/groonga/admin_html以下にインストールされます。このディレクトリをdocument-rootオプションの値に指定して起動した場合、ウェブブラウザでhttp://hostname:port/index.htmlにアクセスすると、ウェブベースのデータベース管理ツールを使用できます。

--protocol <protocol>
    http,gqtpのいずれかを指定します。(デフォルトはgqtp)

--log-path <path>
    ログを出力するファイルのパスを指定します。(デフォルトは/var/log/groonga/groonga.logです)

--query-log-path <path>
    クエリーログを出力するファイルのパスを指定します。(デフォルトでは出力されません)

-t, --max-threads <max threasd>
    最大で利用するスレッド数を指定します。(デフォルトはマシンのCPUコア数と同じ数です)

--pid-path <path>
    PIDを保存するパスを指定します。(デフォルトでは保存しません)

--config-path <path>
    設定ファイルのパスを指定します。設定ファイルは以下のようなフォーマットになります。:

    # '#'以降はコメント。
    ; ';'以降もコメント。
    # 'キー = 値'でオプションを指定。
    pid-file = /var/run/groonga.pid
    # '='の前後の空白はは無視される。↓は↑と同じ意味。
    pid-file=/var/run/groonga.pid
    # 'キー'は'--XXX'スタイルのオプション名と同じものが使える。
    # 例えば、'--pid-path'に対応するキーは'pid-path'。
    # ただし、キーが'config-path'のオプションは無視される。

--cache-limit <limit>
    キャッシュ数の最大値を指定します。(デフォルトは100です)

--default-match-escalation-threshold <threshold>
    検索の挙動をエスカレーションする閾値を指定します。(デフォルトは0です)

  引数

dest
    使用するデータベースのパス名を指定します。

    クライアントモードの場合は接続先のホスト名とポート番号を指定します(デフォルト値は'localhost:10041')。ポート番号を指定しない場合には、10041が指定されたものとします。

command [args]
    スタンドアロンおよびクライアントモードの場合は、実行するコマンドとその引数をコマンドライン引数に指定できます。コマンドライン引数にcommandを与えなかった場合は、標準入力から一行ずつEOFに達するまでコマンド文字列を読み取り、順次実行します。

  コマンド

groongaコマンドを通してデータベースを操作する命令をコマンドと呼びます。コマンドは主にC言語で記述され、groongaプロセスにロードすることによって使用できるようになります。 それぞれのコマンドは一意な名前と、0個以上の引数を持ちます。

引数は以下の2種類の方法のいずれかで指定することができます。:

形式1: コマンド名 値1 値2,..
形式2: コマンド名 --引数名1 値1 --引数名2 値2,..

形式1でコマンドを実行する場合は、定義された順番で値を指定しなければならず、途中の引数の値を省略することはできません。形式2でコマンドを実行する場合は、「--引数名」のように引数の名前を明示しなければならない代わりに、任意の順番で引数を指定することが可能で、途中の引数の指定を省略することもできます。

標準入力からコマンド文字列を与える場合は、コマンド名と引数名と値は、空白( )で区切ります。空白や、記号「"'()」のうちいずれかを含む値を指定したい場合は、シングルクォート(')かダブルクォート(")で値を囲みます。値として指定する文字列の中では、改行文字は'n'に置き換えて指定します。また、引用符に使用した文字を値の中で指定する場合には、その文字の前にバックスラッシュ('') を指定します。バックスラッシュ文字自身を値として指定する場合には、その前にバックスラッシュを指定します。

'\'文字で継続行であることを明示してコマンドリストを記述することができます。

table_create --name Terms \
             --flags TABLE_PAT_KEY \
             --key_type ShortText \
             --default_tokenizer TokenBigram

  組み込みコマンド

以下のコマンドは組み込みコマンドとして予め定義されています。

status
    groongaプロセスの状態を表示します。

table_list
    DBに定義されているテーブルのリストを表示します。

column_list
    テーブルに定義されているカラムのリストを表示します。

table_create
    DBにテーブルを追加します。

column_create
    テーブルにカラムを追加します。

table_remove
    DBに定義されているテーブルを削除します。

column_remove
    テーブルに定義されているカラムを削除します。

view_add
    VIEW型のテーブルに要素となるテーブルを定義します。

load
    テーブルにレコードを挿入します。

select
    テーブルに含まれるレコードを検索して表示します。

define_selector
    検索条件をカスタマイズした新たな検索コマンドを定義します。

quit
    データベースとのセッションを終了します。

shutdown
    サーバ(デーモン)プロセスを停止します。

log_level
    ログ出力レベルを設定します。

log_put
    ログ出力を行います。

clearlock
    ロックを解除します。

  例

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

% groonga -n /tmp/hoge.db quit
%

作成済みのデータベースにテーブルを定義します。:

% groonga /tmp/hoge.db table_create Table 0 ShortText
[[0]]
%

サーバを起動します。:

% groonga -d /tmp/hoge.db
%

httpサーバとして起動します。:

% groonga -d -p 80 --protocol http --document-root /usr/share/groonga/admin_html /tmp/hoge.db
%

サーバに接続し、テーブル一覧を表示します。:

% groonga -c localhost table_list
[[0],[["id","name","path","flags","domain"],[256,"Table","/tmp/hoge.db.0000100",49152,14]]]
%

  groonga-httpd

  概要

groonga-httpdはgroongaサーバーとHTTPプロトコルで通信するプログラムです。 機能的には、 groonga-server-http と同じです。 groonga-server-http はHTTPサーバーとしては最小限の機能しか持ちませんが、groonga-httpdは nginx を組み込むことでnginxが準拠しているHTTPの仕様と機能をすべて利用できます。

groonga-httpdにはHTML + JavaScriptで実装された管理ツールが標準で付属しています。ウェブブラウザでhttp://hostname:port/にアクセスすると、管理ツールを利用できます。

  書式

groonga-httpd [nginx options]

  使い方

  設定をする

まずは、データベースを指定するためにgroonga-httpdの設定ファイルを編集する必要があります。次のように/etc/groonga/httpd/groonga-httpd.confを編集して groonga_database ディレクティブを有効にしてます。

# Match this to the file owner of groonga database files if groonga-httpd is
# run as root.
#user groonga;
...
http {
  ...
  # Don't change the location; currently only /d/ is supported.
  location /d/ {
    groonga on; # <= This means to turn on groonga-httpd.
    # Specify an actual database and enable this.
    groonga_database /var/lib/groonga/db/db;
  }
  ...
}

次に、groonga-httpdを実行してください。すぐにターミナルに制御が戻ってきます。これはgroonga-httpdはデフォルトでデーモンプロセスになるからです。

% groonga-httpd

  クエリーを実行する

動作を確認するため、簡単なクエリー（ /reference/commands/status ）をリクエストしてみます。

実行例:

% curl http://localhost:10041/d/status
[
  [
    0,
    1337566253.89858,
    0.000355720520019531
  ],
  {
    "uptime": 0,
    "max_command_version": 2,
    "n_queries": 0,
    "cache_hit_rate": 0.0,
    "version": "2.1.0",
    "alloc_count": 152,
    "command_version": 1,
    "starttime": 1356678595,
    "default_command_version": 1
  }
]

  管理ツールを使う

補足ですが、 http://localhost:10041/ にアクセスすると管理ツールを利用できます。

  終了する

最後に、次のコマンドで動作中のgroonga-httpdデーモンを終了できます。

% groonga-httpd -s stop

  設定ディレクティブ

このセクションでは重要なディレクティブのみ説明します。重要なディレクティブとはgroonga-http特有のディレクティブと性能に関するディレクティブです。

以下のディレクティブはgroonga-httpdの設定ファイル中で使用することができます。デフォルトでは、設定ファイルは/etc/groonga/httpd/groonga-httpd.confに置かれています。

  groonga-httpd特有のディレクティブ

以下のディレクティブはnginxが提供しているものではなく、groonga-httpd関連の設定をするためにgroonga-httpdが提供しているディレクティブです。

  groonga

書式:

groonga on | off;

Default
    groonga off;

Context
    location

    この location ブロックでgroongaを使うかどうかを指定します。デフォルトは off です。groongaを使うためには on を指定してください。

    例:

    location /d/ {
      groonga on;  # Enables groonga under /d/... path
    }
    location /d/ {
      groonga off; # Disables groonga under /d/... path
    }

  groonga_database

書式:

groonga_database /path/to/groonga/database;

Default
    groonga_database /usr/local/var/lib/groonga/db/db;

Context
    http, server, location

    groongaデータベースのパスを指定します。このディレクティブは必須です。

  groonga_base_path

書式:

groonga_base_path /d/;

Default
    location の名前と同じ値。

Context
    location

    URIのベースパスを指定します。groongaは command を実行するために /d/command?parameter1=value1&... というパスを使います。groonga-httpdでもこのパスの形式を使いますが、groonga-httpdは /other-prefix/command?parameter1=value1&... というように /d/ ではなく別のプレフィックスを使った形式もサポートしています。この別の形式もサポートするために、groonga-httpdはリクエストURIの先頭からベースパスを削除し、先頭に /d/ を追加します。このパスの変換をすることにより、ユーザーはプレフィックスをカスタムできるようになりますが、groongaは常に /d/command?parameter1=value1&... という形式で処理できます。

    通常、このディレクティブを使う必要はありません。このディレクティブはコマンド毎に設定をしたい場合に使います。

    以下は /reference/commands/shutdown コマンドに認証をかける設定例です。:

    groonga_database /var/lib/groonga/db/db;
    location /d/shutdown {
      groonga on;
      # groonga_base_path is needed.
      # Because /d/shutdown is handled as the base path.
      # Without this configuration, /d/shutdown/shutdown path is required
      # to run shutdown command.
      groonga_base_path /d/;
      auth_basic           "manager is required!";
      auth_basic_user_file "/etc/managers.htpasswd";
    }
    location /d/ {
      groonga on;
      # groonga_base_path doesn't needed.
      # Because location name is the base path.
    }

  性能関連のディレクティブ

以下のディレクティブはgronoga-httpdの性能に関連しているディレクティブです。

  worker_processes

最適なパフォーマンスを得るためには、CPU数あるいはコア数と同じ数になるようにこのディレクティブを設定してください。大抵の場合、groongaのクエリーはCPU負荷が高いものとなり、複数のCPU/コアを使い切るためには、このディレクティブを設定する必要があります。

このディレクティブはgroonga-httpdのディレクティブではなく、nginxのディレクティブです。詳細は、 http://wiki.nginx.org/CoreModule#worker_processes を参照してください。

デフォルトで、このディレクティブには1が設定されています。

  利用可能なnginxモジュール

全てのHTTPの標準モジュールが利用可能です。PCRE（Perl Compatible Regular Expressions）がない場合はHttpRewriteModuleは無効になります。標準モジュールの一覧は、 http://wiki.nginx.org/Modules を参照してください。

  groonga HTTPサーバー

  名前

groonga HTTPサーバー

  書式

groonga -d --protocol http DB_PATH

  説明

groongaサーバを起動する時に--protocolオプションにhttpを指定すると、httpで通信可能になります。また、--document-root によって静的ページのパスを指定すると、httpリクエストに指定されたURIに対応する、パス配下に置かれたファイルを出力します。

groongaにはHTML + JavaScriptで実装された管理ツールが標準で付属しています。--document-rootを指定しない場合は管理ツールがインストールされているパスが指定されたとみなされますので、ウェブブラウザでhttp://hostname:port/にアクセスすると、管理ツールを利用できます。

  コマンド

httpを指定して起動したgroongaサーバに対しても、他のモードで起動したgroongaと同じコマンドが使用できます。

コマンドは、複数の引数をとります。引数にはそれぞれ名前があります。また、特殊な引数である「output_type」と「command_version」があります。

スタンドアロンやクライアントモードでは、コマンドは以下のような形式で指定します。 形式1: コマンド名 値1 値2,..

形式2: コマンド名 --引数名1 値1 --引数名2 値2,..

形式1と形式2は混在させることができます。これらの形式では、output_typeという引数名を用いてoutput_typeを指定します。

httpでgroongaサーバと通信する際には、以下のような形式でコマンドを指定します。:

形式: /d/コマンド名.output_type?引数名1=値1&引数名2=値2&...

ただし、コマンド名、引数名、値はURLエンコードが必要です。

GETメソッドのみが使用可能です。

output_typeにはjson, tsv, xmlが指定可能です。

command_versionはコマンドの仕様の互換性を指定します。詳細は /reference/command/command_version を参照してください。

  返値

output_typeの指定に従って、コマンドの実行結果を出力します。

  groonga-suggest-create-dataset

  名前

groonga-suggest-create-dataset - Defines schema for a suggestion dataset

  SYNOPSTIS

groonga-suggest-create-dataset [options] DATABASE DATASET

  DESCTIPION

groonga-suggest-create-dataset creates a dataset for /suggest. A database has many datasets. This command just defines schema for a suggestion dataset.

  オプション

None.

  EXIT STATUS

TODO

  FILES

TODO

  例

TODO

  参考

/suggest

  出力

groongaは以下の出力形式をサポートしています。

•   JSON

•   XML

•   TSV（タブ区切り形式）

•   MessagePack

    JSONがデフォルトの出力形式です。

  使い方

groongaには以下のクエリーインターフェイスがあります。

•   コマンドライン

•   HTTP

    それぞれのインターフェイスで出力形式を変更する方法は異なります。

  コマンドライン

groonga DB_PATH または groonga -c でコマンドラインクエリーインターフェイスを使うことができます。これらのgroongaコマンドでは > `` というプロンプトが表示されます。クエリーインターフェイスでは ``output_type オプションで出力形式を指定できます。

output_type オプションを指定しない場合はJSON形式の出力になります:

> status
[[0,1327721628.10738,0.000131845474243164],{"alloc_count":142,"starttime":1327721626,"uptime":2,"version":"1.2.9-92-gb87d9f8","n_queries":0,"cache_hit_rate":0.0,"command_version":1,"default_command_version":1,"max_command_version":2}]

明示的に output_type に json を指定することもできます。この場合はJSON形式の出力になります:

> status --output_type json
[[0,1327721639.08321,7.93933868408203e-05],{"alloc_count":144,"starttime":1327721626,"uptime":13,"version":"1.2.9-92-gb87d9f8","n_queries":0,"cache_hit_rate":0.0,"command_version":1,"default_command_version":1,"max_command_version":2}]

XML形式の出力にする場合は output_type に xml を指定します:

> status --output_type xml
<?xml version="1.0" encoding="utf-8"?>
<RESULT CODE="0" UP="1327721649.61095" ELAPSED="0.000126361846923828">
<RESULT>
<TEXT>alloc_count</TEXT>
<INT>146</INT>
<TEXT>starttime</TEXT>
<INT>1327721626</INT>
<TEXT>uptime</TEXT>
<INT>23</INT>
<TEXT>version</TEXT>
<TEXT>1.2.9-92-gb87d9f8</TEXT>
<TEXT>n_queries</TEXT>
<INT>0</INT>
<TEXT>cache_hit_rate</TEXT>
<FLOAT>0.0</FLOAT>
<TEXT>command_version</TEXT>
<INT>1</INT>
<TEXT>default_command_version</TEXT>
<INT>1</INT>
<TEXT>max_command_version</TEXT>
<INT>2</INT></RESULT>
</RESULT>

TSV形式の出力にする場合は output_type に tsv を指定します::<

> status --output_type tsv
0     1327721664.82675        0.000113964080810547
"alloc_count" 146
"starttime"   1327721626
"uptime"      38
"version"     "1.2.9-92-gb87d9f8"
"n_queries"   0
"cache_hit_rate"      0.0
"command_version"     1
"default_command_version"     1
"max_command_version" 2
END

MessagePack形式の出力にする場合は output_type に msgpack を指定します::<

> status --output_type msgpack
(... omitted because MessagePack is binary data format. ...)

  HTTP

groonga --protocol http -s DB_PATH でHTTPクエリーインターフェイスを使うことができます。groonga HTTPサーバーはデフォルトで10041番ポートで起動します。このクエリーインターフェイスでは拡張子で出力形式を指定します。

拡張子を指定しない場合はJSON形式の出力になります:

% curl http://localhost:10041/d/status
[[0,1327809294.54311,0.00082087516784668],{"alloc_count":155,"starttime":1327809282,"uptime":12,"version":"1.2.9-92-gb87d9f8","n_queries":0,"cache_hit_rate":0.0,"command_version":1,"default_command_version":1,"max_command_version":2}]

明示的に json 拡張子を指定することもできます。この場合はJSON形式の出力になります:

% curl http://localhost:10041/d/status.json
[[0,1327809319.01929,9.5367431640625e-05],{"alloc_count":157,"starttime":1327809282,"uptime":37,"version":"1.2.9-92-gb87d9f8","n_queries":0,"cache_hit_rate":0.0,"command_version":1,"default_command_version":1,"max_command_version":2}]

XML形式の出力にする場合は xml 拡張子を指定します:

% curl http://localhost:10041/d/status.xml
<?xml version="1.0" encoding="utf-8"?>
<RESULT CODE="0" UP="1327809339.5782" ELAPSED="9.56058502197266e-05">
<RESULT>
<TEXT>alloc_count</TEXT>
<INT>159</INT>
<TEXT>starttime</TEXT>
<INT>1327809282</INT>
<TEXT>uptime</TEXT>
<INT>57</INT>
<TEXT>version</TEXT>
<TEXT>1.2.9-92-gb87d9f8</TEXT>
<TEXT>n_queries</TEXT>
<INT>0</INT>
<TEXT>cache_hit_rate</TEXT>
<FLOAT>0.0</FLOAT>
<TEXT>command_version</TEXT>
<INT>1</INT>
<TEXT>default_command_version</TEXT>
<INT>1</INT>
<TEXT>max_command_version</TEXT>
<INT>2</INT></RESULT>
</RESULT>

TSV形式の出力にする場合は tsv 拡張子を指定します:

% curl http://localhost:10041/d/status.tsv
0     1327809366.84187        8.44001770019531e-05
"alloc_count" 159
"starttime"   1327809282
"uptime"      84
"version"     "1.2.9-92-gb87d9f8"
"n_queries"   0
"cache_hit_rate"      0.0
"command_version"     1
"default_command_version"     1
"max_command_version" 2
END

MessagePack形式の出力にする場合は msgpack 拡張子を指定します:

% curl http://localhost:10041/d/status.msgpack
(... omitted because MessagePack is binary data format. ...)

  コマンド

コマンドはクエリーAPIでもっとも重要な処理単位です。コマンドでgroongaに処理をリクエストします。

このセクションではコマンドについての説明と組み込みのコマンドについて説明します。

  コマンドバージョン

  概要

groonga1.1からコマンドバージョンという概念が導入されます。コマンドバージョンは、selectやloadなどのgroongaのコマンドの仕様の互換性を表します。groongaパッケージのバージョンが新しくなったとしても、同一のコマンドバージョンが使用可能であるなら、すべてのコマンドについて互換性が保証されます。コマンドバージョンが異なれば、同じ名前のコマンドであっても、動作に互換性がない可能性があります。

あるバージョンのgroongaは、二つのコマンドバージョンを同時にサポートするようになります。 使用するコマンドバージョンは、groongaを起動する際のコマンドラインオプションないしコンフィグファイルにdefault-commnad-versionパラメータを与えることによって指定できます。また、個々のコマンドを実行する際に、command_versionパラメータを与えることによっても指定することができます。

コマンドバージョンは1からはじまり、更新されるたびに1ずつ大きくなります。現状のgroongaのコマンドの仕様はcommand-version 1という扱いになります。次回提供するgroongaは、command-version 1とcommand-version 2の二つをサポートすることになります。

  バージョンの位置づけ

あるバージョンのgroongaにおいてサポートされるコマンドバージョンは、develop, stable,deprecatedのいずれかの位置づけとなります。

develop
    まだ開発中であり、仕様が変更される可能性があります。

stable
    使用可能であり仕様も安定しています。その時点で使用することが推奨されます。

deprecated
    使用可能であり仕様も安定していますが、廃止予定であり使用が推奨されません。

    あるバージョンのgroongaがサポートする二つのコマンドバージョンのうち、いずれか一つが必ずstableの位置づけとなります。残りの一つは、developないしdeprecatedとなります。

    たとえば下記のようにgroongaのサポートするコマンドバージョンは推移します。:

    groonga1.1: command-version1=stable     command-version2=develop
    groonga1.2: command-version1=deprecated command-version2=stable
    groonga1.3: command-version2=stable     command-version3=develop
    groonga1.4: command-version2=deprecated command-version3=stable
    groonga1.5: command-version3=stable     command-version4=develop

    あるコマンドバージョンははじめにdevelop扱いとしてリリースされ、やがてstableに移行します。 その後二世代経過するとそのコマンドバージョンはdeprecated扱いとなります。さらに次のコマンドバージョンがリリースされると、deprecatedだったコマンドバージョンはサポート対象外となります。

    default-commnad-versionパラメータやcommand_versionパラメータを指定せずにgroongaコマンドを実行した際には、その時点でstableであるコマンドバージョンが指定されたものとみなします。

    groongaプロセス起動時に、default-command-versionパラメータにstable扱いでないコマンドバージョンを指定した場合には、警告メッセージがログファイルに出力されます。また、サポート範囲外のコマンドバージョンを指定した場合にはエラーとなり、プロセスは速やかに停止します。

  コマンドバージョンの指定方法

コマンドバージョンの指定方法はgroonga実行モジュールの引数として指定する方法と各コマンドの引数として指定する方法があります。

  default-command-versionパラメータ

groonga実行モジュールの引数としてdefault-command-versionパラメータを指定できます。 (configファイルの中に指定することも可能です)

実行例:

groonga --default-command-version 1

そのプロセスで実行するすべてのコマンドについて、デフォルトのコマンドバージョンとして指定されたバージョンを使用します。指定されたコマンドバージョンがstableであった場合にはなんのメッセージも表示されずそのまま起動します。指定されたコマンドバージョンがdevelopあるいはdeprecatedであった場合には、groonga.logファイルに警告メッセージを出力します。指定されたコマンドバージョンがサポート対象外であった場合には標準エラー出力にエラーメッセージを出力し、プロセスは速やかに終了します。

  command_versionパラメータ

select,loadなどのすべてのgroongaコマンドにcommand_versionが指定できます。

実行例:

select --command_version 1 --table tablename

指定されたコマンドバージョンでコマンドを実行します。指定されたコマンドバージョンがサポート対象外であった場合にはエラーが返されます。command-versionが指定されなかった場合は、当該プロセス起動時にdefault-command-versionに指定した値が指定されたものとみなします。

  出力形式

  概要

コマンドは実行結果をJSONまたはMessagePack、XML、TSVのどれかで出力します。

JSONとMessagePackの出力は同じ構造になっています。XMLとTSVはそれぞれ独自の構造になっています。

JSONまたはMessagePackの利用を推奨します。XMLは目視で結果を確認する時に便利です。TSVは特殊な用途では有用です。通常はTSVを使う必要はありません。

  JSONとMessagePack

このセクションではJSONとMessagePack形式を使った時のコマンド実行結果の構造を説明します。MessagePackはバイナリー形式なのでここでは構造を示すためにJSONを使います。バイナリー形式はドキュメントには向いていません。

JSON形式、MessagePack形式のときは以下のような構造になります:

[HEADER, BODY]

実行例:

[
  [
    0,
    1337566253.89858,
    0.000355720520019531
  ],
  [
    [
      [
        1
      ],
      [
        [
          "_id",
          "UInt32"
        ],
        [
          "_key",
          "ShortText"
        ],
        [
          "content",
          "Text"
        ],
        [
          "n_likes",
          "UInt32"
        ]
      ],
      [
        2,
        "Groonga",
        "I started to use groonga. It's very fast!",
        10
      ]
    ]
  ]
]

この例では、以下の部分が HEADER に相当します:

[
  0,
  1337566253.89858,
  0.000355720520019531
]

BODY に相当する部分は以下です:

[
  [
    [
      1
    ],
    [
      [
        "_id",
        "UInt32"
      ],
      [
        "_key",
        "ShortText"
      ],
      [
        "content",
        "Text"
      ],
      [
        "n_likes",
        "UInt32"
      ]
    ],
    [
      2,
      "Groonga",
      "I started to use groonga. It's very fast!",
      10
    ]
  ]
]

  HEADER

HEADER は配列です。 HEADER の内容にはいくつかのパターンがあります。

  成功した場合

コマンドが成功した場合は HEADER には3つの要素があります:

[0, UNIX_TIME_WHEN_COMMAND_IS_STARTED, ELAPSED_TIME]

最初の値は常に 0 です。

UNIX_TIME_WHEN_COMMAND_IS_STARTED はコマンドの実行が始まったときの時刻です。時刻は1970-01-01 00:00:00から経過した秒数で表現されています。 ELAPSED_TIME はコマンドの実行にかかった時間です。単位は秒です。 UNIX_TIME_WHEN_COMMAND_IS_STARTED も ELAPSED_TIME も浮動小数点数です。小数部分はナノ秒を表します。

  エラーの場合

エラーの場合、 HEADER には4個または5個の要素があります:

[
  RETURN_CODE,
  UNIX_TIME_WHEN_COMMAND_IS_STARTED,
  ELAPSED_TIME,
  ERROR_MESSAGE,
  ERROR_LOCATION
]

ERROR_LOCATION は HEADER には含まれないかもしれませんが、他の4個の要素は常に含まれます。

RETURN_CODE は0ではない値です。リターンコードの詳細は return_code を見てください。

UNIX_TIME_WHEN_COMMAND_IS_STARTED と ELAPSED_TIME は成功した時と同じです。

ERROR_MESSAGE はエラーメッセージです。文字列です。

ERROR_LOCATION は存在しないことがあります。もし、エラーが発生した場所の情報を収集できていた場合は ERROR_LOCATION が含まれます。 ERROR_LOCATION は配列です。 ERROR_LOCATION は1個または2個の要素を含みます:

[
  LOCATION_IN_GROONGA,
  LOCATION_IN_INPUT
]

LOCATION_IN_GROONGA はgroonga内でエラーが発生したソースコードの場所です。この情報はgroonga開発者には役に立ちますが、ユーザーの役には立ちません。 LOCATION_IN_GROONGA は配列です。 LOCATION_IN_GROONGA には3個の要素があります:

[
  FUNCTION_NAME,
  SOURCE_FILE_NAME,
  LINE_NUMBER
]

FUNCTION_NAME はエラーが発生した関数の名前です。

SOURCE_FILE_NAME はエラーが発生した箇所を含んだgroongaのソースコードのファイル名です。

LINE_NUMBER はエラーが発生した箇所の SOURCE_FILE_NAME での行番号です。

LOCATION_IN_INPUT は存在しないことがあります。 LOCATION_IN_INPUT は入力ファイルでエラーが発生した場所の情報を収集できたときに含まれます。入力ファイルは groonga コマンドのコマンドラインオプション --file で指定できます。 LOCATION_IN_GROONGA は配列です。 LOCATION_IN_GROONGA には3個の要素があります:

[
  INPUT_FILE_NAME,
  LINE_NUMBER,
  LINE_CONTENT
]

INPUT_FILE_NAME はエラーが発生した入力ファイルのファイル名です。

LINE_NUMBER はエラーが発生した箇所の INPUT_FILE_NAME での行番号です。

LINE_CONTENT は INPUT_FILE_NAME 内の LINE_NUMBER 行目の内容です。

  BODY

BODY の内容は実行したコマンドに依存します。 BODY がないこともあります。

エラーが発生した時に、 BODY にエラーメッセージが入っていることもあります。

  XML

TODO

  TSV

TODO

  参考

•   return_code describes about return code.

  リターンコード

  概要

リターンコードは処理が成功したかどうかを示すために使われます。もし、処理が成功していなければリターンコードはエラーの種類を示します。

リターンコードはCのAPIでもクエリーAPIでも使われます。CのAPIでは grn_ctx_t::rc でリターンコードを確認できます。クエリーAPIではヘッダー要素を見るとリターンコードを確認できます。クエリーAPIでのヘッダー要素については output_format を参照してください。

  一覧

以下はリターンコードの一覧です。 GRN_SUCCESS (= 0) は処理が成功したことを示しています。負の値のリターンコードはエラーの種類を表しています。 GRN_END_OF_DATA は特別なリターンコードです。このリターンコードはCのAPIでだけ使われていて、クエリーAPIにはでてきません。

•   0: GRN_SUCCESS

•   1: GRN_END_OF_DATA

•   -1: GRN_UNKNOWN_ERROR

•   -2: GRN_OPERATION_NOT_PERMITTED

•   -3: GRN_NO_SUCH_FILE_OR_DIRECTORY

•   -4: GRN_NO_SUCH_PROCESS

•   -5: GRN_INTERRUPTED_FUNCTION_CALL

•   -6: GRN_INPUT_OUTPUT_ERROR

•   -7: GRN_NO_SUCH_DEVICE_OR_ADDRESS

•   -8: GRN_ARG_LIST_TOO_LONG

•   -9: GRN_EXEC_FORMAT_ERROR

•   -10: GRN_BAD_FILE_DESCRIPTOR

•   -11: GRN_NO_CHILD_PROCESSES

•   -12: GRN_RESOURCE_TEMPORARILY_UNAVAILABLE

•   -13: GRN_NOT_ENOUGH_SPACE

•   -14: GRN_PERMISSION_DENIED

•   -15: GRN_BAD_ADDRESS

•   -16: GRN_RESOURCE_BUSY

•   -17: GRN_FILE_EXISTS

•   -18: GRN_IMPROPER_LINK

•   -19: GRN_NO_SUCH_DEVICE

•   -20: GRN_NOT_A_DIRECTORY

•   -21: GRN_IS_A_DIRECTORY

•   -22: GRN_INVALID_ARGUMENT

•   -23: GRN_TOO_MANY_OPEN_FILES_IN_SYSTEM

•   -24: GRN_TOO_MANY_OPEN_FILES

•   -25: GRN_INAPPROPRIATE_I_O_CONTROL_OPERATION

•   -26: GRN_FILE_TOO_LARGE

•   -27: GRN_NO_SPACE_LEFT_ON_DEVICE

•   -28: GRN_INVALID_SEEK

•   -29: GRN_READ_ONLY_FILE_SYSTEM

•   -30: GRN_TOO_MANY_LINKS

•   -31: GRN_BROKEN_PIPE

•   -32: GRN_DOMAIN_ERROR

•   -33: GRN_RESULT_TOO_LARGE

•   -34: GRN_RESOURCE_DEADLOCK_AVOIDED

•   -35: GRN_NO_MEMORY_AVAILABLE

•   -36: GRN_FILENAME_TOO_LONG

•   -37: GRN_NO_LOCKS_AVAILABLE

•   -38: GRN_FUNCTION_NOT_IMPLEMENTED

•   -39: GRN_DIRECTORY_NOT_EMPTY

•   -40: GRN_ILLEGAL_BYTE_SEQUENCE

•   -41: GRN_SOCKET_NOT_INITIALIZED

•   -42: GRN_OPERATION_WOULD_BLOCK

•   -43: GRN_ADDRESS_IS_NOT_AVAILABLE

•   -44: GRN_NETWORK_IS_DOWN

•   -45: GRN_NO_BUFFER

•   -46: GRN_SOCKET_IS_ALREADY_CONNECTED

•   -47: GRN_SOCKET_IS_NOT_CONNECTED

•   -48: GRN_SOCKET_IS_ALREADY_SHUTDOWNED

•   -49: GRN_OPERATION_TIMEOUT

•   -50: GRN_CONNECTION_REFUSED

•   -51: GRN_RANGE_ERROR

•   -52: GRN_TOKENIZER_ERROR

•   -53: GRN_FILE_CORRUPT

•   -54: GRN_INVALID_FORMAT

•   -55: GRN_OBJECT_CORRUPT

•   -56: GRN_TOO_MANY_SYMBOLIC_LINKS

•   -57: GRN_NOT_SOCKET

•   -58: GRN_OPERATION_NOT_SUPPORTED

•   -59: GRN_ADDRESS_IS_IN_USE

•   -60: GRN_ZLIB_ERROR

•   -61: GRN_LZO_ERROR

•   -62: GRN_STACK_OVER_FLOW

•   -63: GRN_SYNTAX_ERROR

•   -64: GRN_RETRY_MAX

•   -65: GRN_INCOMPATIBLE_FILE_FORMAT

•   -66: GRN_UPDATE_NOT_ALLOWED

•   -67: GRN_TOO_SMALL_OFFSET

•   -68: GRN_TOO_LARGE_OFFSET

•   -69: GRN_TOO_SMALL_LIMIT

•   -70: GRN_CAS_ERROR

•   -71: GRN_UNSUPPORTED_COMMAND_VERSION

  参考

•   output_format はクエリーAPIでのレスポンスの中でどこにリターンコードがあるかを説明しています。

•   /spec/gqtp: GQTPプロトコルもステータスとしてリターンコードを使っていますが、ステータスは2バイトの符号なし整数です。そのため、GQTPプロトコルでは、負の値のリターンコードは正の値のステータスになります。GQTPプロトコルのステータスの値を2バイトの符号付き整数として扱うとステータスをリターンコードに変換できます。

  cache_limit

  名前

cache_limit - cacheサイズの設定・取得

  書式

cache_limit max

  説明

groonga組込コマンドの一つであるcache_limitについて説明します。組込コマンドは、groonga実行ファイルの引数、標準入力、またはソケット経由でgroongaサーバにリクエストを送信することによって実行します。

cache_limitは、クエリキャッシュの最大件数を取得したり設定したりします。

  引数

max クエリキャッシュの最大件数を整数で指定します。 maxが指定されなかった場合には、クエリキャッシュの最大件数は変更せず、 現在の設定値のみが返されます。

  返値

  json

[以前の設定値]

以前の設定値 すでに設定されていたクエリキャッシュの最大件数を返す。

  例

cache_limit 4
[100]

  check

  名前

check - オブジェクトの状態表示

  書式

check obj

  説明

groonga組込コマンドの一つであるcheckについて説明します。組込コマンドは、groonga実行ファイルの引数、標準入力、またはソケット経由でgroongaサーバにリクエストを送信することによって実行します。

checkコマンドは、groongaプロセス内の指定したオブジェクトの状態を表示します。主にデータベースが壊れた場合など異常時の問題解決のために使用することを想定しています。デバッグ用のため、返値のフォーマットが安定しているということは保証されません。（フォーマットが変更される可能性が高い）

  引数

obj 状態を表示するオブジェクトの名前を指定します。

  返値

  json形式

チェックするオブジェクトにより返される値が変わります。

インデックスカラムの場合:

下記のような配列が出力されます。
  [インデックスの状態, バッファの状態1, バッファの状態2, ...]

インデックスの状態 には下記の項目がハッシュ形式で出力されます。 flags 指定されているフラグ値です。16進数で表現されています。

max sid セグメントのうち最も大きなIDです。

number of garbage segments ゴミセグメントの数です。

number of array segments 配列セグメントの数です。

max id of array segment 配列セグメントのうち最も大きなIDです。

number of buffer segments バッファセグメントの数です。

max id of buffer segment バッファセグメントのうち最も大きなIDです。

max id of physical segment in use 使用中の論理セグメントのうち最も大きなIDです。

number of unmanaged segments 管理されていないセグメントの数です。

total chunk size チャンクサイズの合計です。

max id of chunk segments in use 使用中のチャンクセグメントのうち最も大きなIDです。

number of garbage chunk 各チャンク毎のゴミの数です。

バッファの状態 には下記の項目がハッシュ形式で出力されます。 buffer id バッファIDです。

chunk size チャンクのサイズです。

buffer term バッファ内にある語の一覧です。各語の状態は以下のような配列となっています。 [語, バッファに登録されている語のID, 用語集に登録されている語のID, バッファ内でのサイズ, チャンク内でのサイズ]

buffer free バッファの空き容量です。

size in buffer バッファの使用量です。

nterms バッファ内にある語の数です。

nterms with chunk バッファ内にある語のうち、チャンクを使っている語の数です。

  例

テーブルTermsのインデックスカラムnameの状態を表示します。:

check Terms.name
[{"flags":"00008202",
  "max sid":1,
  "number of garbage segments":0,
  "number of array segments":1,
  "max id of array segment":1,
  "number of buffer segments":110,
  "max id of buffer segment":111,
  "max id of physical segment in use":111,
  "number of unmanaged segments":4294967185,
  "total chunk size":7470239,
  "max id of chunk segments in use":127,
  "number of garbage chunk":[0,0,0,0,0,0,0,0,2,2,0,0,0,0,0]},
 {"buffer id":0,
  "chunk size":94392,
  "buffer term":["596","59777","6",...],
  "buffer free":152944,
  "size in buffer":7361,
  "nterms":237,
  "nterms with chunk":216,
  "buffer id":1,
  "chunk size":71236,
  "buffer term":[["に述",18149,18149,2,25,6,6],
                 ["に追",4505,4505,76,485,136,174],
                 ["に退",26568,26568,2,9,2,2],
                 ...],
  "buffer free":120000,
  "size in buffer":11155,
  "nterms":121,
  "nterms with chunk":116},
  {"buffer id":1,
   ...},
  ...]

  clearlock

  名前

clearlock - オブジェクトにセットされたロックを解除する

  書式

clearlock objname

  説明

groonga組込コマンドの一つであるclearlockについて説明します。組込コマンドは、groonga実行ファイルの引数、標準入力、またはソケット経由でgroongaサーバにリクエストを送信することによって実行します。

clearlockは、対象となるオブジェクト(データベース,テーブル,インデックス等)を指定し、オブジェクトにかけられたロックを再帰的に解除します。

  引数

objname 対象となるオブジェクト名を指定します。空の場合、開いているdbオブジェクトが対象となります。

  返値

  json形式

[成功かどうかのフラグ]

成功かどうかのフラグ エラーが生じなかった場合にはtrue、エラーが生じた場合にはfalseを返す。

  例

開いているデータベースのロックをすべて解除する:

clearlock
[true]

テーブル名 Entry のカラム body のロックを解除する:

clearlock Entry.body
[true]

  関連項目

load

  column_create

  名前

column_create - カラムの追加

  書式

column_create table name flags type [source]

  説明

groonga組込コマンドの一つであるcolumn_createについて説明します。組込コマンドは、groonga実行ファイルの引数、標準入力、またはソケット経由でgroongaサーバにリクエストを送信することによって実行します。

column_createは、使用しているデータベースのテーブルに対してカラムを追加します。

  引数

table カラムを追加するテーブルの名前を指定します。

name 作成するカラムの名前を指定します。カラム名は、テーブルの中で一意でなければなりません。

ピリオド('.'), コロン(':')を含む名前のカラムは作成できません。また、アンダースコア('_')で始まる名前は予約済みであり、使用できません。

flags カラムの属性を表す以下の数値か、パイプ('|')で組み合わせたシンボル名を指定します。

0, COLUMN_SCALAR
    単一の値が格納できるカラムを作成します。

1, COLUMN_VECTOR
    複数の値の配列を格納できるカラムを作成します。

2, COLUMN_INDEX
    インデックス型のカラムを作成します。

    インデックス型のカラムについては、flagsの値に以下の値を加えることによって、追加の属 性を指定することができます。

128, WITH_SECTION
    段落情報を格納するインデックスを作成します。

256, WITH_WEIGHT
    ウェイト情報を格納するインデックスを作成します。

512, WITH_POSITION
    位置情報を格納するインデックス(完全転置インデックス)を作成します。

    type 値の型を指定します。groongaの組込型か、同一データベースに定義済みのユーザ定義型、定義済みのテーブルを指定することができます。

    source インデックス型のカラムを作成した場合は、インデックス対象となるカラムをsource引数に指定します。

  返値

  json形式

[成功かどうかのフラグ]

成功かどうかのフラグ エラーが生じなかった場合にはtrue、エラーが生じた場合にはfalseを返す。

  例

テーブルEntryに、ShortText型の値を格納するカラム、bodyを作成します。:

column_create Entry body --type ShortText
[true]

テーブルTermに、Entryテーブルのbodyカラムの値を対象とする完全転置インデックス型カラム、entry_bodyを作成します。:

column_create Term entry_body COLUMN_INDEX|WITH_POSITION Entry body
[true]

  column_list

  名前

column_list - テーブルに定義されているカラムのリスト表示

  書式

column_list table

  説明

groonga組込コマンドの一つであるcolumn_listについて説明します。組込コマンドは、groonga実行ファイルの引数、標準入力、またはソケット経由でgroongaサーバにリクエストを送信することによって実行します。

column_listはテーブルに定義されているカラムをリスト表示します。

  引数

table
    カラム情報を出力するテーブルの名前を指定します。

  返値

  json形式

カラム名一覧を以下の形式で返却します。:

[[[カラム情報名1,カラム情報型1],...], カラム情報1,...]

カラム情報名n カラム情報n には複数の情報が含まれますが、そこに入る情報がどんな内容かを示す名前を出力します。 情報名は以下の通りです。

id カラムオブジェクトに割り当てられたID

name カラム名

path カラム値を格納するファイル名

type スカラ型、ベクタ型、インデックス型の種別

flags カラムのflags属性

domain カラムの値の属する型

range テーブルのkeyの型

source インデックスカラムのとき、インデックス対象カラム名の配列

カラム情報型n カラム情報の型を出力します。

カラム情報n カラム情報名n で示された情報の配列を出力します。 情報の順序は カラム情報名n の順序と同じです。

  例

column_list Entry
[[["id", "UInt32"],
  ["name","ShortText"],
  ["path","ShortText"],
  ["type","ShortText"],
  ["flags","ShortText"],
  ["domain", "ShortText"],
  ["range", "ShortText"],
  ["source","ShortText"]],
 [258,
  "Entry.body",
  "test.db.0000102",
  "var",
  "COLUMN_SCALAR|COMPRESS_NONE|PERSISTENT",
  "Entry",
  "ShortText",
  []]]

注: 実際は改行が入りません。

  column_remove

  名前

column_remove - テーブルに定義されているカラムの削除

  書式

column_remove table name

  説明

groonga組込コマンドの一つであるcolumn_removeについて説明します。組込コマンドは、groonga実行ファイルの引数、標準入力、またはソケット経由でgroongaサーバにリクエストを送信することによって実行します。

column_removeはテーブルに定義されているカラムを削除します。 また、付随するインデックスも削除されます。[#]_

  引数

table
    削除対象のカラムが定義されているテーブルの名前を指定します。

name
    削除対象のカラム名を指定します。

  返値

  json形式

[成功かどうかのフラグ]

成功かどうかのフラグ エラーが生じなかった場合にはtrue、エラーが生じた場合にはfalseを返す。

  例

column_remove Entry body
[true]
脚注

[1] マルチセクションインデックスの一部である場合も、インデックスが削除されます。

  define_selector

  名前

define_selector - 検索コマンドを定義

  書式

define_selector name table [match_columns [query [filter [scorer [sortby
                [output_columns [offset [limit [drilldown [drilldown_sortby
                [drilldown_output_columns [drilldown_offset [drilldown_limit]]]]]]]]]]]]]

  説明

groonga組込コマンドの一つであるdefine_selectorについて説明します。組込コマンドは、groonga実行ファイルの引数、標準入力、またはソケット経由でgroongaサーバにリクエストを送信することによって実行します。

define_selectorは、検索条件をカスタマイズした新たな検索コマンドを定義します。

  引数

name 定義するselectorコマンドの名前を指定します。

table 検索対象のテーブルを指定します。

match_columns 追加するselectorコマンドのmatch_columns引数のデフォルト値を指定します。

query 追加するselectorコマンドのquery引数のデフォルト値を指定します。

filter 追加するselectorコマンドのfilter引数のデフォルト値を指定します。

scorer 追加するselectorコマンドのscorer引数のデフォルト値を指定します。

sortby 追加するselectorコマンドのsortby引数のデフォルト値を指定します。

output_columns 追加するselectorコマンドのoutput_columns引数のデフォルト値を指定します。

offset 追加するselectorコマンドのoffset引数のデフォルト値を指定します。

limit 追加するselectorコマンドのlimit引数のデフォルト値を指定します。

drilldown 追加するselectorコマンドのdrilldown引数のデフォルト値を指定します。

drilldown_sortby 追加するselectorコマンドのdrilldown_sortby引数のデフォルト値を指定します。

drilldown_output_columns 追加するselectorコマンドのdrilldown_output_columns引数のデフォルト値を指定します。

drilldown_offset 追加するselectorコマンドのdrilldown_offset引数のデフォルト値を指定します。

drilldown_limit 追加するselectorコマンドのdrilldown_limit引数のデフォルト値を指定します。

  返値

  json形式

[成功かどうかのフラグ]

成功かどうかのフラグ エラーが生じなかった場合にはtrue、エラーが生じた場合にはfalseを返す。

  例

テーブルEntryの全レコード・全カラムの値を出力するselectorコマンドを定義します。:

define_selector entry_selector Entry
[true]

  関連項目

/reference/grn_expr

  defrag

  名前

defrag - オブジェクトにセットされたロックを解除する

  書式

defrag objname threshold

  説明

groonga組込コマンドの一つであるdefragについて説明します。組込コマンドは、groonga実行ファイルの引数、標準入力、またはソケット経由でgroongaサーバにリクエストを送信することによって実行します。

defragは、対象となるオブジェクト(データベースか可変長サイズカラム)を指定し、オブジェクトのフラグメンテーションを解消します。

  引数

objname 対象となるオブジェクト名を指定します。空の場合、開いているdbオブジェクトが対象となります。

  返値

  json形式

[フラグメンテーション解消を実行したセグメントの数]

フラグメンテーション解消を実行したセグメントの数 フラグメンテーション解消を実行したセグメントの数を返す。

  例

開いているデータベースのフラグメンテーションを解消する:

defrag
[300]

テーブル名 Entry のカラム body のフラグメンテーションを解消する:

defrag Entry.body
[30]

  delete

  名前

delete - 一件のレコードの削除

  書式

delete table [key [id [filter]]]

  説明

groonga組込コマンドの一つであるdeleteについて説明します。組込コマンドは、groonga実行ファイルの引数、標準入力、またはソケット経由でgroongaサーバにリクエストを送信することによって実行します。

deleteは、使用しているデータベースのテーブルに1件のレコードを削除します。

  引数

table レコードを削除しようとするテーブルの名前を指定します。

key 削除するレコードの主キー値を指定します。主キーなしのテーブルの場合はこのパラメータを指定しても無視されます(idパラメータを代わりに指定します)。

id レコードIDによってレコードを指定します。idパラメータを指定する場合は、keyパラメータを指定してはいけません。

filter script形式のgrn_expr文字列によってレコードを指定します。filterパラメータを指定する場合は、id及びkeyパラメータを指定してはいけません。

返値 ---

  json形式

[成功かどうかのフラグ]

成功かどうかのフラグ エラーが生じなかった場合にはtrue、エラーが生じた場合にはfalseを返す。

  例

テーブルEntryからレコードを削除します。:

delete Entry abandon
[true]

  関連項目

load

  dump

  名前

dump - データベースのスキーマとデータを出力する

  書式

dump [tables]

  説明

groonga組込コマンドの一つであるdumpについて説明します。組込コマンドは、groonga実行ファイルの引数、標準入力、またはソケット経由でgroongaサーバにリクエストを送信することによって実行します。

dumpはデータベースのスキーマとデータを後から読み込めるフォーマットで出力します。dumpの結果は大きくなるため、主にコマンドラインから使うことを想定しています。データベースのバックアップが主な利用方法です。

dumpが出力するフォーマットは直接groongaが解釈できるフォーマットです。そのため、以下のようにしてデータベースをコピーすることができます。:

% groonga original/db dump > dump.grn
% mkdir backup
% groonga -n backup/db < dump.grn

  引数

tables 出力対象のテーブルを「,」（カンマ）区切りで指定します。存在しないテーブルを指定した場合は無視されます。

  返値

データベースのスキーマとデータをgroongaの組み込みコマンド呼び出し形式で出力します。output_type指定は無視されます。

  例

データベース内のすべてのデータを出力:

> dump
table_create LocalNames 48 ShortText
table_create Entries 48 ShortText
column_create Entries local_name 0 LocalNames
column_create LocalNames Entries_local_name 2 Entries local_name
...
load --table LocalNames
[
["_key"],
["Items"],
["BLT"],
...
]
...

データベース内のスキーマと特定のテーブルのデータのみ出力:

> dump --tables Users,Sites
table_create Users TABLE_HASH_KEY ShortText
column_create Users name COLUMN_SCALAR ShortText
table_create Comments TABLE_PAT_KEY ShortText
column_create Comments text COLUMN_SCALAR ShortText
table_create Sites TABLE_NO_KEY
column_create Sites url COLUMN_SCALAR ShortText
load --table Users
[
["_key"],
["mori"],
["yu"],
...
]
load --table Sites
[
["_id","url"],
[1,"http://groonga.org/"],
[2,"http://qwik.jp/senna/"],
...
]

  load

  名前

load - データのロード

  書式

load values table [columns [ifexists [input_type]]]

  説明

groonga組込コマンドの一つであるloadについて説明します。組込コマンドは、groonga実行ファイルの引数、標準入力、またはソケット経由でgroongaサーバにリクエストを送信することによって実行します。

loadは、使用しているデータベースのテーブルにレコードを登録し、カラムの値を更新します。

  引数

values input_typeに指定する形式で登録するレコードの値を表現した文字列を渡します。

input_typeがjsonである場合には、以下のいずれかの形式が使用できます。

形式1 [[カラム名1, カラム名2,..], [カラム値1, カラム値2,..], [カラム値1, カラム値2,..],..]

形式2 [{カラム名1: カラム値1, カラム名2: カラム値2}, {カラム名1: カラム値1, カラム名2: カラム値2},..]

    形式1の[カラム名1, カラム名2,..]の要素はcolumns引数が省略された場合のみ有効です。

    対象のテーブルが主キーを持つテーブルであった場合は、カラム名の中に'_key'(主キーを示す疑似カラム名)が含まれていなければなりません。

    values引数が省略された場合には、括弧の対応が取れるまで標準入力からvaluesの値を読み取ります。引数として値を指定する場合は、文字列のエスケープが必要ですが、標準入力から与える文字列はエスケープする必要がありません。

    続きの文字列については、空白文字(' ')をエスケープする必要はありません。

    table レコードを追加しようとするテーブルの名前を指定します。

    columns テーブルに登録するレコードに値を設定するカラム名のリストを、カンマ区切りで指定します。

    ifexists 指定した主キーに対応するレコードが既にテーブルに登録済みであった場合に実行するscript形式のgrn_expr文字列を指定します。ifexistsにgrn_exprが指定された場合は、式の値が真である場合に限り、その他のカラムの値が更新されます。(デフォルトはtrue)

    input_type 入力形式を指定します。JSONのみに対応しています。

  返値

  JSON形式

[登録件数]

登録件数 テーブルに登録されたレコードの件数が返されます。

  例

テーブルEntryにレコードを登録します。:

load --table Entry --input_type json --values [{\"_key\":\"abandon\",\"body\":\"放棄する\"}]
[1]

標準入力からvaluesの値を与えます。:

load --table Entry --input_type json
[
{"_key": "abbreviate", "body": "短縮する"}
]
[1]

  関連項目

/reference/grn_expr

  log_level

  名前

log_level - ログ出力レベルの設定

  書式

log_level level

  説明

groonga組込コマンドの一つであるlog_levelについて説明します。組込コマンドは、groonga実行ファイルの引数、標準入力、またはソケット経由でgroongaサーバにリクエストを送信することによって実行します。

log_levelは、ログ出力レベルを設定します。

  引数

level 設定するログ出力レベルの値を以下のいずれかで指定します。 EMERG ALERT CRIT error warning notice info debug

  返値

  json形式

[成功かどうかのフラグ]

成功かどうかのフラグ エラーが生じなかった場合にはtrue、エラーが生じた場合にはfalseを返す。

  例

log_level warning
[true]

  関連項目

log_put log_reopen

  log_put

  名前

log_put - ログ出力

  書式

log_put level message

  説明

groonga組込コマンドの一つであるlog_putについて説明します。組込コマンドは、groonga実行ファイルの引数、標準入力、またはソケット経由でgroongaサーバにリクエストを送信することによって実行します。

log_putは、ログにmessageを出力します。

  引数

level 設定するログ出力レベルの値を以下のいずれかで指定します。 EMERG ALERT CRIT error warning notice info debug

message 出力する文字列を指定します。

  返値

  json形式

[成功かどうかのフラグ]

成功かどうかのフラグ エラーが生じなかった場合にはtrue、エラーが生じた場合にはfalseを返す。

  例

log_put ERROR ****MESSAGE****
[true]

  関連項目

log_level log_reopen

  log_reopen

  名前

log_reopen - ログファイルの再読み込み

  書式

log_reopen

  説明

groonga組込コマンドの一つであるlog_reopenについて説明します。組込コマンドは、groonga実行ファイルの引数、標準入力、またはソケット経由でgroongaサーバにリクエストを送信することによって実行します。

log_reopenは、ログファイルを再読み込みします。

現在、デフォルトのログ関数を用いている場合のみに対応しています。

  引数

ありません。

  返値

  json形式

[成功かどうかのフラグ]

成功かどうかのフラグ エラーが生じなかった場合にはtrue、エラーが生じた場合にはfalseを返す。

  例

log_reopen
[true]

  log_reopenを用いたログのローテーション

1.  ログファイルをmvなどで移動する。 ログはmvで移動された先のファイルに書き込まれる。

2.  log_reopenコマンドを実行する。

3.  既存のログファイル名と同じファイル名で、新たなログファイルが作成される。 今後のログは新たなログファイルに書き込まれる。

  関連項目

log_level log_put

  normalize

ご用心 normalize コマンドは実験的な機能です。このコマンドは将来的に変更されるかも知れません。

  概要

normalize コマンドは指定したノーマライザーでテキストを正規化します。

normalize コマンドを使うのにテーブルを作成する必要はありません。このコマンドは、ノーマライザーの結果を確認するのに便利です。

  構文

normalize コマンドは normalizer と string という二つの引数をとります。これらの引数はどちらも必須です。

normalize normalizer string

  使い方

以下は normalize コマンドの簡単な使用例です。

実行例:

normalize NormalizerAuto "aBcDe 123"
# [[0, 1337566253.89858, 0.000355720520019531], "abcde 123"]

  引数

このセクションでは normalizer の引数について説明します。

  必須引数

必須引数は二つあります。 normalizer と string です。

  normalizer

ノーマライザーの名前を指定します。今のところ normalize コマンドは NormalizerAuto もしくは NormalizerNFKC51 を組み込みノーマライザーとして受けつけます。もし他のノーマライザーを使いたい場合には、追加したいノーマライザーを /reference/commands/register コマンドで登録する必要があります。

  string

正規化したい文字列を指定します。

  戻り値

[HEADER, normalized]

HEADER HEADERのフォーマットは [0, UNIX_TIME_WHEN_COMMAND_IS_STARTED, ELAPSED_TIME] です。HEADERについては /reference/command/output_format を参照してください。

normalized normalizedは指定したノーマライザーによる正規化されたテキストです。

  参考

•   /reference/normalizers

  quit

  名前

quit - セッション終了

  書式

quit

  説明

groonga組込コマンドの一つであるquitについて説明します。組込コマンドは、groonga実行ファイルの引数、標準入力、またはソケット経由でgroongaサーバにリクエストを送信することによって実行します。

quitは、groongaプロセスとのセッションを終了します。クライアントプロセスならばgroongaプロセスとの接続を切ります。

  引数

ありません。

  返値

ありません。

  例

quit

  register

  概要

register コマンドはプラグインを登録します。プラグインを使う前にプラグインを登録する必要があります。

同じデータベースに対しては1つのプラグインについて一度だけ register` コマンドを実行すれば十分です。これは、登録されたプラグイン情報はデータベースに記録されているからです。 groonga プロセスを再起動したときは、 register コマンドを実行しなくてもすでに登録されているプラグインを読み込みます。

ノート 今のところ、登録したプラグインは削除できません。

  構文

register の引数は path だけです。これは必須の引数です:

register path

  使い方

これは ${PREFIX}/lib/groonga/plugins/query_expanders/tsv.so に含まれている QueryExpanderTSV クエリー展開オブジェクトを登録する例です。

実行例:

register query_expanders/tsv
# [[0, 1337566253.89858, 0.000355720520019531], true]

${PREFIX}/lib/groonga/plugins/ と拡張子（ .so ）は省略可能です。これらは自動で補完されます。

register /usr/lib/groonga/plugins/query_expanders/tsv.so というように絶対パスを指定することもできます。

  戻り値

register が成功したときは以下のようにボディは true になります:

[HEADER, true]

register が失敗すると、エラーの詳細は HEADER に含まれます。

HEADER については /reference/command/output_format を参照してください。

  select

  概要

select はテーブルから指定された条件にマッチするレコードを検索し、見つかったレコードを出力します。

select は最も重要なgroongaのコマンドです。groongaの力を最大限に活かすためには select を理解する必要があります。

  構文

select には多くの引数があります。必須の引数は table だけで、残りは省略できます。:

select table
       [match_columns=null]
       [query=null]
       [filter=null]
       [scorer=null]
       [sortby=null]
       [output_columns="_id, _key, *"]
       [offset=0]
       [limit=10]
       [drilldown=null]
       [drilldown_sortby=null]
       [drilldown_output_columns=null]
       [drilldown_offset=0]
       [drilldown_limit=10]
       [cache=yes]
       [match_escalation_threshold=0]
       [query_expansion=null]
       [query_flags=ALLOW_PRAGMA|ALLOW_COLUMN|ALLOW_UPDATE|ALLOW_LEADING_NOT|NONE]

  使い方

例を使いながら select の使い方を学びましょう。このセクションではよく使われる使い方を紹介します。

使い方を示すために使うスキーマ定義とサンプルデータは以下の通りです。

実行例:

table_create Entries TABLE_HASH_KEY ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Entries content COLUMN_SCALAR Text
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Entries n_likes COLUMN_SCALAR UInt32
# [[0, 1337566253.89858, 0.000355720520019531], true]
table_create Terms TABLE_PAT_KEY|KEY_NORMALIZE ShortText --default_tokenizer TokenBigram
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Terms entries_key_index COLUMN_INDEX|WITH_POSITION Entries _key
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Terms entries_content_index COLUMN_INDEX|WITH_POSITION Entries content
# [[0, 1337566253.89858, 0.000355720520019531], true]
load --table Entries
[
{"_key":    "The first post!",
 "content": "Welcome! This is my first post!",
 "n_likes": 5},
{"_key":    "Groonga",
 "content": "I started to use groonga. It's very fast!",
 "n_likes": 10},
{"_key":    "Mroonga",
 "content": "I also started to use mroonga. It's also very fast! Really fast!",
 "n_likes": 15},
{"_key":    "Good-bye Senna",
 "content": "I migrated all Senna system!",
 "n_likes": 3},
{"_key":    "Good-bye Tritonn",
 "content": "I also migrated all Tritonn system!",
 "n_likes": 3}
]
# [[0, 1337566253.89858, 0.000355720520019531], 5]

ブログエントリ用の Entries テーブルがあります。各エントリはタイトルと内容と「いいね！」数を持っています。タイトルは Entries のキーとします。内容は Entries.content カラムの値とします。「いいね！」数は Entries.n_likes カラムの値とします。

Entries._key カラムと Entries.content カラムには TokenBigram トークナイザーを使ったインデックスを作成します。そのため、 Entries._key と Entries.content は両方とも全文検索できます。

これで例を示すためのスキーマとデータの準備ができました。

  簡単な使い方

上記のスキーマとデータを使った一番簡単な使い方は以下の通りです。これは Entries テーブルのすべてのレコードを出力します。

実行例:

select Entries
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         5
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         1,
#         "The first post!",
#         "Welcome! This is my first post!",
#         5
#       ],
#       [
#         2,
#         "Groonga",
#         "I started to use groonga. It's very fast!",
#         10
#       ],
#       [
#         3,
#         "Mroonga",
#         "I also started to use mroonga. It's also very fast! Really fast!",
#         15
#       ],
#       [
#         4,
#         "Good-bye Senna",
#         "I migrated all Senna system!",
#         3
#       ],
#       [
#         5,
#         "Good-bye Tritonn",
#         "I also migrated all Tritonn system!",
#         3
#       ]
#     ]
#   ]
# ]

どうしてこのコマンドがすべてのレコードを出力するのでしょうか？理由は2つです。1つ目の理由はこのコマンドが検索条件を何も指定していないからです。検索条件を指定しないとすべてのレコードがマッチします。2つ目の理由は全レコード数が5だからです。 select コマンドはデフォルトでは最大10レコードを出力します。この例では5レコードしかありません。これは10よりも少ないのですべてのレコードを出力します。

  検索条件

検索条件は query または filter で指定します。 query と filter を両方指定することもできます。この場合は query と filter の両方の条件にマッチしたレコードが出力されます。

  検索条件: query

query はWebページの検索ボックス用に用意されています。例えば、google.co.jpにあるような検索ボックスです。 query の検索条件はスペース区切りでキーワードを指定します。例えば、 検索 エンジン は 検索 と エンジン という2つのキーワードを含むレコードを検索します。

通常は query 引数は全文検索条件を指定するために使います。全文検索条件以外も指定できますが、その用途には filter 引数の方が向いています。

query 引数で全文検索条件を指定する場合は、 match_columns 引数と一緒に使います。 match_columns はどのカラムまたはインデックスを使って query を検索するかを指定します。

以下は簡単な query の使用例です。

実行例:

select Entries --match_columns content --query fast
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         2,
#         "Groonga",
#         "I started to use groonga. It's very fast!",
#         10
#       ],
#       [
#         3,
#         "Mroonga",
#         "I also started to use mroonga. It's also very fast! Really fast!",
#         15
#       ]
#     ]
#   ]
# ]

この select コマンドは Entries テーブルの中から content カラムの値に fast を含んでいるレコードを検索します。

query はクエリー構文という構文を使いますが、詳細はここでは説明しません。詳細は /reference/grn_expr/query_syntax を参照してください。

  検索条件: filter

filter は複雑な検索条件を指定するために用意されています。ECMAScriptのような構文で filter に検索条件を指定します。

以下は簡単な filter の使用例です。

実行例:

select Entries --filter 'content @ "fast" && _key == "Groonga"'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         2,
#         "Groonga",
#         "I started to use groonga. It's very fast!",
#         10
#       ]
#     ]
#   ]
# ]

この select コマンドは Entries テーブルの中の content カラムの値に fast という単語を含んでいて、かつ、 _key が Groonga のレコードを検索します。このコマンドの中には @ と && と == という3つの演算子があります。 @ は全文検索用の演算子です。 && と == はECMAScriptと同じ意味です。 && が論理積用の演算子で == が等価演算子です。

filter にはもっと演算子や構文があります。例えば、 (...) を使った検索条件のグループ化などです。しかし、ここでは詳細は説明しません。詳細は /reference/grn_expr/script_syntax を参照してください。

  ページング

offset と limit を指定することで出力されるレコードの範囲を指定できます。以下は2番目のレコードだけを出力する例です。

実行例:

select Entries --offset 1 --limit 1
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         5
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         2,
#         "Groonga",
#         "I started to use groonga. It's very fast!",
#         10
#       ]
#     ]
#   ]
# ]

offset は0基点です。 --offset 1 は2番目以降のレコードを出力するという意味になります。

limit は出力レコード数の最大値を指定します。 --limit 1 は多くても1レコードを出力するという意味になります。もし、1つもレコードがマッチしていなければ select コマンドはどのレコードも出力しません。

  全レコード数

--limit 0 を使うとレコードの内容は取得せずに全レコード数だけを取得できます。

実行例:

select Entries --limit 0
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         5
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ]
#     ]
#   ]
# ]

--limit 0 はマッチしたレコード数だけを取得したいときにも便利です。

  引数

このセクションではすべての引数について説明します。引数はカテゴリわけしています。

  必須引数

table だけが必須の引数です。

  table

検索対象のテーブルを指定します。 table は必ず指定しなければいけません。

存在しないテーブルを指定するとエラーが返ります。

実行例:

select Nonexistent
# [
#   [
#     -22,
#     1337566253.89858,
#     0.000355720520019531,
#     "invalid table name: <Nonexistent>",
#     [
#       [
#         "grn_select",
#         "proc.c",
#         542
#       ]
#     ]
#   ]
# ]

  検索関係の引数

検索関係の引数がいくつかあります。一般的には、検索ボックスを実装するために match_columns と query 引数を使い、複雑な検索機能を実装するために filter 引数を使います。

query と filter を指定した場合は、 query と filter にマッチしたレコードが選択されます。 query と filter のどちらも指定しなかった場合はすべてのレコードが選択されます。

  match_columns

query 引数の値で全文検索をするときに使うデフォルトの検索対象カラムを指定します。全文検索対象のカラムは query 引数でも指定できます。検索対象カラムを match_columns で指定する場合と query で指定する場合の違いは重みを指定できるかどうかです。 match_columns では重みを指定できますが、 query では指定できません。

重みは検索対象カラムの相対的な重要度です。重みの大きい検索対象カラムでマッチした場合は小さい検索対象カラムでマッチした場合よりも多くのヒットスコアがつきます。デフォルトの重みは1です。

以下は簡単な match_columns の使用例です。

実行例:

select Entries --match_columns content --query fast --output_columns '_key, _score'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "_score",
#           "Int32"
#         ]
#       ],
#       [
#         "Groonga",
#         1
#       ],
#       [
#         "Mroonga",
#         2
#       ]
#     ]
#   ]
# ]

--match_columns content はデフォルトの全文検索対象カラムに content カラムを使用し、その重みは1、という意味になります。 --output_columns '_key, _score' はこの select コマンドがマッチしたレコードの _key の値と _score の値を出力する、ということを指定しています。

_score の値に注目してください。 _score の値は query 引数の値に何個マッチしたかになっています。この例では、 query 引数の値は fast です。 _score の値が1ということは content カラムの中に fast が1つだけあるということです。 _score の値が2ということは content カラムの中に fast が2つあるということです。

重みを指定するためには column * weight という構文を使います。以下は重みの使用例です。

実行例:

select Entries --match_columns 'content * 2' --query fast --output_columns '_key, _score'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "_score",
#           "Int32"
#         ]
#       ],
#       [
#         "Groonga",
#         2
#       ],
#       [
#         "Mroonga",
#         4
#       ]
#     ]
#   ]
# ]

--match_columns 'content * 2' はデフォルトの全文検索用カラムとして content カラムを使い、その重みは2という意味です。

_score の値に注目してください。 _score の値が2倍になっています。これは重みを2にしたからです。

デフォルトの全文検索対象カラムとして複数のカラムを指定することができます。複数のカラムを指定した場合はすべてのカラムに対して全文検索が行われ、ヒットスコアが積算されます。つまり、 query 引数の値がどれか1つでも全文検索対象カラムにマッチしたら、そのレコードはマッチしたものとして扱われます。

複数のカラムを指定するには column1 * weight1 || column2 * weight2 || ... という構文を使います。 * weight は省略することができます。省略した場合は重みが1になります。以下は複数カラムの使用例です。

実行例:

select Entries --match_columns '_key * 10 || content' --query groonga --output_columns '_key, _score'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "_score",
#           "Int32"
#         ]
#       ],
#       [
#         "Groonga",
#         11
#       ]
#     ]
#   ]
# ]

--match_columns '_key * 10 || content' はデフォルト検索対象カラムが _key カラムと content カラムで、 _key カラムの重みは10、 content カラムの重みは1という意味です。この重み付けは _key カラムの値は content カラムの値よりも重要だという意味になります。この例では、ブログエントリのタイトルはブログエントリの内容よりも重要だということです。

  query

クエリーテキストを指定します。通常、全文検索をするために match_columns 引数と一緒に使います。 query 引数はWebページにある全文検索フォームで使いやすいように設計されています。クエリーテキストは /reference/grn_expr/query_syntax という書式を使います。この書式はGoogleの検索フォームのように一般的な検索フォームと似ています。例えば、 word1 word2 は word1 と word2 を含んでいるレコードを検索するという意味になります。 word1 OR word2 は word1 または word2 を含んでいるレコードを検索するという意味になります。

以下は論理積を使った検索の簡単な例です。

実行例:

select Entries --match_columns content --query "fast groonga"
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         2,
#         "Groonga",
#         "I started to use groonga. It's very fast!",
#         10
#       ]
#     ]
#   ]
# ]

この select コマンドは Entries テーブルの中から content カラムの値に fast と groonga の2つの単語を含んでいるレコードを検索します。

以下は論理和を使った検索の簡単な例です。

実行例:

select Entries --match_columns content --query "groonga OR mroonga"
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         2,
#         "Groonga",
#         "I started to use groonga. It's very fast!",
#         10
#       ],
#       [
#         3,
#         "Mroonga",
#         "I also started to use mroonga. It's also very fast! Really fast!",
#         15
#       ]
#     ]
#   ]
# ]

この select コマンドは Entries テーブルの中から content カラムの値に fast または groonga のどちらかの単語を含んでいるレコードを検索します。

他の構文は /reference/grn_expr/query_syntax を参照してください。

query では全文検索だけではなく他の条件も使えます。例えば、 column:value は column の値が value と等しいという意味です。 column:<value は column の値が value より小さいという意味です。

以下は等価演算子を使った検索の簡単な例です。

実行例:

select Entries --query _key:Groonga
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         2,
#         "Groonga",
#         "I started to use groonga. It's very fast!",
#         10
#       ]
#     ]
#   ]
# ]

この select コマンドは Entries テーブルの中から _key カラムの値が Groonga であるレコードを検索します。

以下は比較演算子を使った検索の簡単な例です。

実行例:

select Entries --query n_likes:<11
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         4
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         1,
#         "The first post!",
#         "Welcome! This is my first post!",
#         5
#       ],
#       [
#         2,
#         "Groonga",
#         "I started to use groonga. It's very fast!",
#         10
#       ],
#       [
#         4,
#         "Good-bye Senna",
#         "I migrated all Senna system!",
#         3
#       ],
#       [
#         5,
#         "Good-bye Tritonn",
#         "I also migrated all Tritonn system!",
#         3
#       ]
#     ]
#   ]
# ]

この select コマンドは Entries テーブルの中から n_likes カラムの値が 11 より小さいレコードを検索します。

他の演算子は /reference/grn_expr/query_syntax を参照してください。

  filter

フィルターテキストを指定します。通常、 filter は複雑な条件を指定するために使います。 filter は query 引数と一緒に使うこともできます。 filter と query を両方指定した場合はそれらを論理積で組み合わせます。つまり、マッチするレコードは filter にも query にもマッチしなければいけないということです。

filter 引数は複雑な条件用に設計されています。フィルターテキストは /reference/grn_expr/script_syntax 書式で指定します。この書式はECMAScriptに似ています。例えば、 column == "value" は column カラムの値が "value" と等しいという意味です。 column < value は column カラムの値が value よりも小さいという意味です。

以下は等価演算子を使った検索の簡単な例です。

実行例:

select Entries --filter '_key == "Groonga"'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         2,
#         "Groonga",
#         "I started to use groonga. It's very fast!",
#         10
#       ]
#     ]
#   ]
# ]

この select コマンドは Entries テーブルの中から _key カラムの値が Groonga であるレコードを検索します。

以下は比較演算子を使った検索の簡単な例です。

実行例:

select Entries --filter 'n_likes < 11'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         4
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         1,
#         "The first post!",
#         "Welcome! This is my first post!",
#         5
#       ],
#       [
#         2,
#         "Groonga",
#         "I started to use groonga. It's very fast!",
#         10
#       ],
#       [
#         4,
#         "Good-bye Senna",
#         "I migrated all Senna system!",
#         3
#       ],
#       [
#         5,
#         "Good-bye Tritonn",
#         "I also migrated all Tritonn system!",
#         3
#       ]
#     ]
#   ]
# ]

この select コマンドは Entries テーブルの中から n_likes カラムの値が 11 より小さいレコードを検索します。

他の演算子は /reference/grn_expr/script_syntax を参照してください。

  高度な検索のための引数

  match_escalation_threshold

検索方法をエスカレーションするかどうかを決定するための閾値を指定します。この閾値はマッチしたレコード数との比較に使われます。マッチしたレコード数がこの閾値以下の場合は検索方法をエスカレーションします。検索方法のエスカレーションについては /spec/search を参照してください。

デフォルトの閾値は0です。これは1つもレコードがマッチしなかったときだけ検索方法をエスカレーションするということです。

デフォルトの閾値は以下の方法でカスタマイズできます。

•   configureの --with-match-escalation-threshold オプション

•   groongaコマンドの --match-escalation-threshold オプション

•   設定ファイルの match-escalation-threshold 設定項目

    以下は簡単な match_escalation_threshold の使用例です。最初の select は match_escalation_threshold 引数がありません。2番目の select は match_escalation_threshold 引数があります。

    実行例:

    select Entries --match_columns content --query groo
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         1
    #       ],
    #       [
    #         [
    #           "_id",
    #           "UInt32"
    #         ],
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "content",
    #           "Text"
    #         ],
    #         [
    #           "n_likes",
    #           "UInt32"
    #         ]
    #       ],
    #       [
    #         2,
    #         "Groonga",
    #         "I started to use groonga. It's very fast!",
    #         10
    #       ]
    #     ]
    #   ]
    # ]
    select Entries --match_columns content --query groo --match_escalation_threshold -1
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         0
    #       ],
    #       [
    #         [
    #           "_id",
    #           "UInt32"
    #         ],
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "content",
    #           "Text"
    #         ],
    #         [
    #           "n_likes",
    #           "UInt32"
    #         ]
    #       ]
    #     ]
    #   ]
    # ]

    最初の select コマンドは Entries テーブルから content カラムの値に groo という単語を含むレコードを検索します。しかし、この検索ではどのレコードにもマッチしません。これは、 TokenBigram トークナイザーは groonga を gr|ro|oo|on|ng|ga ではなく groonga にトークナイズするからです。（ TokenBigramSplitSymbolAlpha は groonga を gr|ro|oo|on|ng|ga にトークナイズします。詳細は /reference/tokenizers を見てください。）つまり、 groonga はインデックスに登録されていますが、 groo はインデックスに登録されていないということです。インデックスに登録されていないので完全一致検索では groo はどのレコードにもマッチしません。このケースでは検索方法のエスカレーションが行われています。なぜならばマッチしたレコード数（0）が match_escalation_threshold （0）の値と等しいからです。非分かち書き検索では groo で1つのレコードがマッチします。

    2番目の select コマンドも Entries テーブルから content カラムの値に groo という単語を含むレコードを検索します。そして、この select コマンドもマッチしません。この場合、マッチしたレコード数（0）が match_escalation_threshold （-1）より大きいので、検索方法をエスカレーションしません。そして、1つもレコードがマッチしません。

  query_expansion

クエリー展開用の引数です。クエリー展開はクエリー中の特定の単語を別の単語に置換します。通常は類義語検索に使います。

query 引数の値を置換するために使うカラムを指定します。この引数の値の書式は「 ${TABLE}.${COLUMN} 」です。例えば、 「 Terms.synonym 」は Terms テーブルの synonym カラムを指定しています。

クエリー展開用のテーブルを「置換テーブル」と呼びます。置換テーブルのキーは ShortText にしてください。そのため、配列テーブル（ TABLE_NO_KEY ）は置換テーブルに使うことはできません。なぜなら、配列テーブルにはキーがないからです。

クエリー展開用のカラムを「置換カラム」と呼びます。置換カラムの値の型は ShortText にしてください。カラムの種類はベクター（ COLUMN_VECTOR ）にしてください。

クエリー展開はクエリーの中にある置換テーブルのキーを置換カラムの値で置換します。 query の中にある単語が置換テーブルのキーだったら、キーに対応する置換カラムの値でその単語を置換します。置換は再帰的に実行しません。これは、置換されたクエリー内に置換対象の単語があっても置換されないということです。

以下は query_expansion の簡単な使用例を示すためのサンプル置換テーブルです。

実行例:

table_create Thesaurus TABLE_PAT_KEY|KEY_NORMALIZE ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Thesaurus synonym COLUMN_VECTOR ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
load --table Thesaurus
[
{"_key": "mroonga", "synonym": ["mroonga", "tritonn", "groonga mysql"]},
{"_key": "groonga", "synonym": ["groonga", "senna"]}
]
# [[0, 1337566253.89858, 0.000355720520019531], 2]

Thesaurus 置換テーブルは2つの類義語があります。 "mroonga" と "groonga" です。ユーザが "mroonga" で検索すると、groongaは "((mroonga) OR (tritonn) OR (groonga mysql))" で検索します。ユーザーが "groonga" で検索すると、groongaは "((groonga) OR (senna))" で検索します。通常、置換テーブルには KEY_NORMALIZE フラグをつけた方がよいです。このフラグを使うと、置換対象の単語が大文字小文字区別せずにマッチするようになります。

これらの類義語の値の中に "mroonga" や "groonga" といったキーの値も含まれていることに注意してください。このように類義語にキーの値も含めることを推奨します。もしキーの値を含めないと、置換した値には元の置換対象の値が含まれません。通常、元の値が含まれていた方がよい検索結果になります。もし、検索してほしくない単語がある場合は、元の単語を含めないでください。例えば、空のベクター値を指定することで「ストップワード」機能を実現することもできます。

以下は簡単な query_expansion の使用例です。

実行例:

select Entries --match_columns content --query "mroonga"
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         3,
#         "Mroonga",
#         "I also started to use mroonga. It's also very fast! Really fast!",
#         15
#       ]
#     ]
#   ]
# ]
select Entries --match_columns content --query "mroonga" --query_expansion Thesaurus.synonym
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         3,
#         "Mroonga",
#         "I also started to use mroonga. It's also very fast! Really fast!",
#         15
#       ],
#       [
#         5,
#         "Good-bye Tritonn",
#         "I also migrated all Tritonn system!",
#         3
#       ]
#     ]
#   ]
# ]
select Entries --match_columns content --query "((mroonga) OR (tritonn) OR (groonga mysql))"
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         3,
#         "Mroonga",
#         "I also started to use mroonga. It's also very fast! Really fast!",
#         15
#       ],
#       [
#         5,
#         "Good-bye Tritonn",
#         "I also migrated all Tritonn system!",
#         3
#       ]
#     ]
#   ]
# ]

最初の select コマンドはクエリー展開を使いません。そのため、 "tritonn" という単語を含んでいるレコードは見つかりません。2番目の select コマンドはクエリー展開を使っています。そのため、 "tritonn" という単語を含んでいるレコードが見つかります。3番目の select コマンドはクエリー展開を使っていませんが、2番目の select コマンドと同じ結果になります。これは、3番目の select コマンドは展開後のクエリーを使っているからです。

それぞれの置換する値は (...) や OR といった /reference/grn_expr/query_syntax を使えます。これらの構文を使うことにより複雑な置換をすることができます。

以下はクエリー構文を使った複雑な置換の使用例です。

実行例:

load --table Thesaurus
[
{"_key": "popular", "synonym": ["popular", "n_likes:>=10"]}
]
# [[0, 1337566253.89858, 0.000355720520019531], 1]
select Entries --match_columns content --query "popular" --query_expansion Thesaurus.synonym
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         2,
#         "Groonga",
#         "I started to use groonga. It's very fast!",
#         10
#       ],
#       [
#         3,
#         "Mroonga",
#         "I also started to use mroonga. It's also very fast! Really fast!",
#         15
#       ]
#     ]
#   ]
# ]

この load コマンドは新しく "popular" という類義語を登録しています。これは ((popular) OR (n_likes:>=10)) に置換されます。置換されたクエリーは、「popular」というのは「popular」という単語を含んでいるか10以上の「いいね！」数を持つエントリという意味になります。

この select コマンドは Entries テーブルの中から n_likes カラムの値が 10 以上のレコードを出力します。

  query_flags

query パラメーターの構文をカスタマイズします。デフォルトでは query パラメーターでカラムの値を更新することはできません。しかし、 query_flags に ALLOW_COLUMN|ALLOW_UPDATE を指定することで query でカラムの値を更新することができます。

指定可能な値は以下の通りです。

•   ALLOW_PRAGMA

•   ALLOW_COLUMN

•   ALLOW_UPDATE

•   ALLOW_LEADING_NOT

•   NONE

    ALLOW_PRAGMA を指定すると query の先頭でプラグマを指定することができます。この機能はまだ実装されていません。

    ALLOW_COLUMN を指定すると match_columns で指定していないカラムでも検索できるように成ります。カラムを指定するには COLUMN:... というような構文を使います。

    ALLOW_UPDATE を指定すると COLUMN:=NEW_VALUE という構文を使って query でカラムの値を更新できます。カラム更新用の構文ではカラムを指定する必要があるため、 ALLOW_COLUMN も一緒に指定する必要があります。

    ALLOW_LEADING_NOT を指定すると -WORD という構文を使って最初の条件として否定条件を指定できます。このクエリーは WORD にマッチしないレコードを検索します。最初の条件に否定条件を使ったクエリーは多くの場合重いクエリーになります。これは多くのレコードにマッチするからです。そのため、このフラグはデフォルトでは無効になっています。もし、このフラグを使う場合は重いクエリーとなるということを十分気をつけてください。

    NONE は単に無視されます。フラグを指定しないときに NONE を使えます。

    これらのフラグは ALLOW_COLUMN|ALLOW_UPDATE のように | で区切って同時に指定することができます。

    デフォルト値は ALLOW_PRAGMA|ALLOW_COLUMN です。

    以下は ALLOW_COLUMN の使用例です。

    実行例:

    select Entries --query content:@mroonga --query_flags ALLOW_COLUMN
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         1
    #       ],
    #       [
    #         [
    #           "_id",
    #           "UInt32"
    #         ],
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "content",
    #           "Text"
    #         ],
    #         [
    #           "n_likes",
    #           "UInt32"
    #         ]
    #       ],
    #       [
    #         3,
    #         "Mroonga",
    #         "I also started to use mroonga. It's also very fast! Really fast!",
    #         15
    #       ]
    #     ]
    #   ]
    # ]

    この select コマンドは Entries テーブルの中から content カラムの値に mroonga を含んでいるレコードを検索します。

    以下は ALLOW_UPDATE の使用例です。

    実行例:

    table_create Users TABLE_HASH_KEY ShortText
    # [[0, 1337566253.89858, 0.000355720520019531], true]
    column_create Users age COLUMN_SCALAR UInt32
    # [[0, 1337566253.89858, 0.000355720520019531], true]
    load --table Users
    [
    {"_key": "alice", "age": 18},
    {"_key": "bob",   "age": 20}
    ]
    # [[0, 1337566253.89858, 0.000355720520019531], 2]
    select Users --query age:=19 --query_flags ALLOW_COLUMN|ALLOW_UPDATE
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         2
    #       ],
    #       [
    #         [
    #           "_id",
    #           "UInt32"
    #         ],
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "age",
    #           "UInt32"
    #         ]
    #       ],
    #       [
    #         1,
    #         "alice",
    #         19
    #       ],
    #       [
    #         2,
    #         "bob",
    #         19
    #       ]
    #     ]
    #   ]
    # ]
    select Users
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         2
    #       ],
    #       [
    #         [
    #           "_id",
    #           "UInt32"
    #         ],
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "age",
    #           "UInt32"
    #         ]
    #       ],
    #       [
    #         1,
    #         "alice",
    #         19
    #       ],
    #       [
    #         2,
    #         "bob",
    #         19
    #       ]
    #     ]
    #   ]
    # ]

    最初の select コマンドは全てのレコードの age カラムの値を 19 にします。二番目の select コマンドは age カラムの値を出力します。

    以下は ALLOW_LEADING_NOT の使用例です。

    実行例:

    select Entries --match_columns content --query -mroonga --query_flags ALLOW_LEADING_NOT
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         4
    #       ],
    #       [
    #         [
    #           "_id",
    #           "UInt32"
    #         ],
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "content",
    #           "Text"
    #         ],
    #         [
    #           "n_likes",
    #           "UInt32"
    #         ]
    #       ],
    #       [
    #         1,
    #         "The first post!",
    #         "Welcome! This is my first post!",
    #         5
    #       ],
    #       [
    #         2,
    #         "Groonga",
    #         "I started to use groonga. It's very fast!",
    #         10
    #       ],
    #       [
    #         4,
    #         "Good-bye Senna",
    #         "I migrated all Senna system!",
    #         3
    #       ],
    #       [
    #         5,
    #         "Good-bye Tritonn",
    #         "I also migrated all Tritonn system!",
    #         3
    #       ]
    #     ]
    #   ]
    # ]

    この select コマンドは Entries テーブルの中から content カラムの値に mroonga を含んでいないレコードを検索します。

    以下は NONE の使用例です。

    実行例:

    select Entries --match_columns content --query 'mroonga OR _key:Groonga' --query_flags NONE
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         1
    #       ],
    #       [
    #         [
    #           "_id",
    #           "UInt32"
    #         ],
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "content",
    #           "Text"
    #         ],
    #         [
    #           "n_likes",
    #           "UInt32"
    #         ]
    #       ],
    #       [
    #         3,
    #         "Mroonga",
    #         "I also started to use mroonga. It's also very fast! Really fast!",
    #         15
    #       ]
    #     ]
    #   ]
    # ]

    この select コマンドは Entries テーブルの中から content カラムの値に mroonga または _key:Groonga のどちらかの単語を含んでいるレコードを検索します。 _key:Groonga が _key カラムの値が Groonga という条件にはならないことに注意してください。これは ALLOW_COLUMN フラグが指定されていないからです。

    /reference/grn_expr/query_syntax も見てください。

  出力関連の引数

  output_columns

出力するカラムを , 区切りで指定します。

以下は簡単な output_columns の使用例です。

実行例:

select Entries --output_columns '_id, _key' --limit 1
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         5
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ]
#       ],
#       [
#         1,
#         "The first post!"
#       ]
#     ]
#   ]
# ]

この select コマンドは _id と _key カラムの値だけを出力します。

* is a special value. It means that all columns that are not /reference/pseudo_column.

以下は * の使用例です。

実行例:

select Entries --output_columns '_key, *' --limit 1
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         5
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         "The first post!",
#         "Welcome! This is my first post!",
#         5
#       ]
#     ]
#   ]
# ]

この select コマンドは _key 擬似カラム、 content カラム、 n_likes カラムの値を出力しますが、 _id 擬似カラムの値は出力しません。

デフォルト値は _id, _key, * です。これは _score 以外の全てのカラムを出力するという意味です。

  sortby

ソートキーを , 区切りで指定します。それぞれのソートキーはカラム名を指定します。

以下は簡単な sortby の使用例です。

実行例:

select Entries --sortby 'n_likes, _id'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         5
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         4,
#         "Good-bye Senna",
#         "I migrated all Senna system!",
#         3
#       ],
#       [
#         5,
#         "Good-bye Tritonn",
#         "I also migrated all Tritonn system!",
#         3
#       ],
#       [
#         1,
#         "The first post!",
#         "Welcome! This is my first post!",
#         5
#       ],
#       [
#         2,
#         "Groonga",
#         "I started to use groonga. It's very fast!",
#         10
#       ],
#       [
#         3,
#         "Mroonga",
#         "I also started to use mroonga. It's also very fast! Really fast!",
#         15
#       ]
#     ]
#   ]
# ]

この select コマンドは n_likes カラムの値で昇順にソートします。 n_likes の値が同じレコードについては _id カラムの値で昇順にソートします。 "Good-bye Senna" と "Good-bye Tritonn" が _id カラムの値でソートしているケースです。

降順でソートしたい場合はカラム名の前に - をつけてください。

以下は降順の sortby の使用例です。

実行例:

select Entries --sortby '-n_likes, _id'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         5
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         3,
#         "Mroonga",
#         "I also started to use mroonga. It's also very fast! Really fast!",
#         15
#       ],
#       [
#         2,
#         "Groonga",
#         "I started to use groonga. It's very fast!",
#         10
#       ],
#       [
#         1,
#         "The first post!",
#         "Welcome! This is my first post!",
#         5
#       ],
#       [
#         4,
#         "Good-bye Senna",
#         "I migrated all Senna system!",
#         3
#       ],
#       [
#         5,
#         "Good-bye Tritonn",
#         "I also migrated all Tritonn system!",
#         3
#       ]
#     ]
#   ]
# ]

この select コマンドは n_likes カラムの値で降順にソートします。しかし、 _id でソートするときは昇順でソートします。

もし、 query または filter 引数を使っているときは、 sortby の中で _score 擬似カラムを使うことができます。

実行例:

select Entries --match_columns content --query fast --sortby -_score --output_columns '_key, _score'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "_score",
#           "Int32"
#         ]
#       ],
#       [
#         "Mroonga",
#         2
#       ],
#       [
#         "Groonga",
#         1
#       ]
#     ]
#   ]
# ]

この select コマンドはマッチしたレコードをヒットスコアで降順にソートし、レコードのキーとヒットスコアを出力します。

query 引数も filter 引数も指定しないで _score を使った場合は、 _score を無視して、ログファイルに警告を出力します。

  offset

出力するレコードの範囲を決めるためのオフセットを指定します。オフセットは0基点です。 --offset 1 は2番目以降のレコードを出力するという意味になります。

実行例:

select Entries --sortby _id --offset 3 --output_columns _key
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         5
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ]
#       ],
#       [
#         "Good-bye Senna"
#       ],
#       [
#         "Good-bye Tritonn"
#       ]
#     ]
#   ]
# ]

この select コマンドは4番目以降のレコードを出力します。

負の値を指定することもできます。負の値の場合は マッチしたレコード数 + offset 番目のレコードから始まる範囲という意味になります。もし、マッチしたレコードが3つあり、 --offset -2 を指定した場合は1番目（ 3 + -2 = 1 ） のレコードから3番目のレコードが出力されます。

実行例:

select Entries --sortby _id --offset -2 --output_columns _key
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         5
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ]
#       ],
#       [
#         "Good-bye Senna"
#       ],
#       [
#         "Good-bye Tritonn"
#       ]
#     ]
#   ]
# ]

この select コマンドは4番目以降のレコードを出力します。なぜなら、全レコード数が 5 だからです。

デフォルト値は 0 です。

  limit

limit は出力レコード数の最大値を指定します。 もし、マッチしたレコード数が limit よりも小さい場合はすべてのレコードが出力されます。

以下は簡単な limit の使用例です。

実行例:

select Entries --sortby _id --offset 2 --limit 3 --output_columns _key
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         5
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ]
#       ],
#       [
#         "Mroonga"
#       ],
#       [
#         "Good-bye Senna"
#       ],
#       [
#         "Good-bye Tritonn"
#       ]
#     ]
#   ]
# ]

この select コマンドは3番目、4番目、5番目のレコードを出力します。

負の値を指定することもできます。負の値の場合は、最大で マッチしたレコード数 + limit + 1 件のレコードを出力するという意味になります。 例えば、 --limit -1 はすべてのレコードを出力します。これはすべてのレコードを表示する場合にとても便利です。

以下は負の値を使った limit の簡単な使用例です。

実行例:

select Entries --limit -1
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         5
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         1,
#         "The first post!",
#         "Welcome! This is my first post!",
#         5
#       ],
#       [
#         2,
#         "Groonga",
#         "I started to use groonga. It's very fast!",
#         10
#       ],
#       [
#         3,
#         "Mroonga",
#         "I also started to use mroonga. It's also very fast! Really fast!",
#         15
#       ],
#       [
#         4,
#         "Good-bye Senna",
#         "I migrated all Senna system!",
#         3
#       ],
#       [
#         5,
#         "Good-bye Tritonn",
#         "I also migrated all Tritonn system!",
#         3
#       ]
#     ]
#   ]
# ]

この select コマンドはすべてのレコードを出力します。

デフォルト値は 10 です。

  scorer

TODO: write in English and add example.

検索条件にマッチする全てのレコードに対して適用するgrn_exprをscript形式で指定します。

scorerは、検索処理が完了し、ソート処理が実行される前に呼び出されます。従って、各レコードのスコアを操作する式を指定しておけば、検索結果のソート順序をカスタマイズできるようになります。

  ファセット関連の引数

  drilldown

TODO: write in English and add example.

グループ化のキーとなるカラム名のリストをカンマ(',')区切りで指定します。検索条件にマッチした各レコードを出力したのちに、drilldownに指定されたカラムの値が同一であるレコードをとりまとめて、それぞれについて結果レコードを出力します。

  drilldown_sortby

TODO: write in English and add example.

drilldown条件に指定されたカラムの値毎にとりまとめられたレコードについて、ソートキーとなるカラム名のリストをカンマ(',')区切りで指定します。sortbyパラメータと同様に昇降順を指定できます。

  drilldown_output_columns

TODO: write in English and add example.

drilldown条件に指定されたカラムの値毎にとりまとめられたレコードについて、出力するカラム名のリストをカンマ(',')区切りで指定します。

  drilldown_offset

TODO: write in English and add example.

drilldown条件に指定されたカラムの値毎にとりまとめられたレコードについて、出力対象となる最初のレコードの番号を0ベースで指定します。デフォルト値は0です。drilldown_offsetに負の値を指定した場合は、ヒットした件数 + drilldown_offsetによって算出される値が指定されたものとみなされます。

  drilldown_limit

TODO: write in English and add example.

drilldown条件に指定されたカラムの値毎にとりまとめられたレコードについて、出力を行うレコードの件数を指定します。デフォルト値は10です。実際には、drilldown_offset + drilldown_limit がヒットした件数を超えない範囲でレコードが出力されます。drilldown_limitに負の値を指定した場合は、ヒットした件数 + drilldown_limit + 1 によって算出される値が指定されたものとみなされます。

  キャッシュ関連の引数

  cache

TODO: write in English and add example.

クエリキャッシュに関する動作を設定します。

no 検索結果をクエリキャッシュに残しません。キャッシュして再利用される可能性が低いクエリに対して用います。キャッシュ容量は有限です。有効なキャッシュが多くヒットするために、このパラメータは有効です。

  返値

TODO: write in English and add example.

以下のようなjson形式で値が返却されます。

[[リターンコード, 処理開始時間, 処理時間], [検索結果, ドリルダウン結果]]

リターンコード grn_rcに対応する数値が返されます。0(GRN_SUCCESS)以外の場合は、続いてエラー内容を示す 文字列が返されます。

処理開始時間 処理を開始した時間について、1970年1月1日0時0分0秒を起点とした秒数を小数で返します。

処理時間 処理にかかった秒数を返します。

検索結果 drilldown条件が実行される前の検索結果が以下のように出力されます。:

[[検索件数], [[カラム名1,カラム型1],..], 検索結果1,..]

検索件数 検索件数が出力されます。

カラム名n output_columnsに指定された条件に従って、対象となるカラム名が出力されます。

カラム型n output_columnsに指定された条件に従って、対象となるカラム型が出力されます。

検索結果n output_columns, offset, limitによって指定された条件に従って各レコードの値が出力されます。

drilldown結果 drilldown処理の結果が以下のように出力されます。:

[[[件数], [[カラム名1,カラム型1],..], 検索結果1,..],..]

件数 drilldownに指定されたカラムの値の異なり数が出力されます。

カラム名n drilldown_output_columnsに指定された条件に従って、対象となるカラム名が出力されます。

カラム型n drilldown_output_columnsに指定された条件に従って、対象となるカラム型が出力されます。

ドリルダウン結果n drilldown_output_columns, drilldown_offset, drilldown_limitによって指定された条件に従って各レコードの値が出力されます。

  参考

•   /reference/grn_expr/query_syntax

•   /reference/grn_expr/script_syntax

  shutdown

  名前

shutdown - サーバプロセスの停止

  書式

shutdown

  説明

groonga組込コマンドの一つであるshutdownについて説明します。組込コマンドは、groonga実行ファイルの引数、標準入力、またはソケット経由でgroongaサーバにリクエストを送信することによって実行します。

shutdownは、接続しているgroongaサーバプロセスを停止します。

  引数

ありません。

  返値

ありません。

  例

shutdown

  status

  名前

status - groongaプロセスの状態表示

  書式

status

  説明

groonga組込コマンドの一つであるstatusについて説明します。組込コマンドは、groonga実行ファイルの引数、標準入力、またはソケット経由でgroongaサーバにリクエストを送信することによって実行します。

statusコマンドは、groongaプロセスの状態を表示します。主にgroongaサーバプロセスに対して使用することを想定しています。

  引数

ありません。

  返値

  json形式

下記の項目がハッシュ形式で出力されます。

alloc_count groongaプロセスの内部でアロケートされ、まだ解放されてないメモリブロックの数を示します。groongaをbuildする際に、configureオプションで --enable-exact-alloc-countが指定されていたならば、正確な値を返します。それ以外の場合は不正確な値を返す場合があります。

開始時間 groongaプロセスが起動した時刻のtvsec値を返します。

稼動時間 groongaプロセスが起動してから経過した秒数を返します。

  例

実行例:

status
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   {
#     "uptime": 6,
#     "max_command_version": 2,
#     "n_queries": 30,
#     "cache_hit_rate": 0.0,
#     "version": "2.1.0",
#     "alloc_count": 280,
#     "command_version": 1,
#     "starttime": 1356678580,
#     "default_command_version": 1
#   }
# ]

  suggest

ノート サジェスト機能の仕様はまだ確定していません。仕様は変更される可能性があります。

  名前

suggest - 指定されたクエリーに対する補完・補正・提案候補を返す。

  書式

suggest types table column query [sortby [output_columns [offset [limit [frequency_threshold [conditional_probability_threshold [prefix_search]]]]]]]

  説明

suggestコマンドは指定されたクエリーに対する補完・補正・提案候補を返します。

補完・補正・提案については /suggest/introduction を参照してください。

  オプション

types
    suggestコマンドでどの種類の候補を返すかを指定します。

    指定できる種類は以下の通りです。

complete
    補完を実行します。

correct
    補正を実行します。

suggest
    提案を実行します。

    1つ以上の種類を指定できます。複数の種類を指定する場合は | で区切ります。以下が例です。: 補正候補を返します:

    correct

    補正候補と提案候補を返します:

    correct|suggest

    補完候補と補正候補と提案候補を返します:

    complete|correct|suggest

table
    item_${データセット名} というフォーマットのテーブル名を指定します。例えば、以下のコマンドでデータセットを作成した場合はテーブル名として item_query を指定します:

    groonga-suggest-create-dataset /tmp/db-path query

column
    table で指定したテーブルにあるふりがな情報を含むカラムを指定します。ふりがなはカタカナで指定します。

query
    補完・補正・提案対象のクエリーを指定します。

sortby
    ソートキーを指定します。

Default:
    -_score

output_columns
    出力するカラムを指定します。

Default:
    _key,_score

offset
    返されるレコードのオフセットを指定します。

Default:
    0

limit
    返されるレコード数を指定します。

Default:
    10

frequency_threshold
    出現頻度に対する閾値を指定します。返されるレコードの _score 値は frequency_threshold 以上になります。

Default:
    100

    conditional_probability_threshold 条件付き確率に対する閾値を指定します。学習データに対して条件付き確率を使います。ここで使う条件付き確率は、入力した query と同じ入力があったときにクエリが検索された確率です。返されるレコードの条件付き確率は conditional_probability_threshold 以上になります。

Default:
    0.2

prefix_search
    補完時に前方一致検索を実行するかどうかを指定します。

    指定可能な値は以下の通りです。

yes 常に前方一致検索を実行します。

no  前方一致検索を実行しません。

auto
    他の検索でレコードが見つからない場合のみ前方一致検索を実行します。

Default:
    auto

similar_search
    補正時に類似検索を実行するかどうかを指定します。

    指定可能な値は以下の通りです。

yes 常に類似検索を実行します。

no  類似検索を実行しません。

auto
    他の検索でレコードが見つからない場合のみ類似検索を実行します。

Default:
    auto

  戻り値

  JSON形式

返されるJSON形式は以下の通りです:

{"type1": [["candidate1", score of candidate1],
           ["candidate2", score of candidate2],
           ...],
 "type2": [["candidate1", score of candidate1],
           ["candidate2", score of candidate2],
           ...],
 ...}

type types で指定した値。

candidate 補完・補正・提案候補。

score of candidate 対応する candidate のスコアです。スコアが高いほど補完・補正・提案候補として有力という意味になります。デフォルトでは候補は score of candidate の降順でソートされています。

  例

以下は補完用の学習データです。

実行例:

load --table event_query --each 'suggest_preparer(_id, type, item, sequence, time, pair_query)'
[
{"sequence": "1", "time": 1312950803.86057, "item": "e"},
{"sequence": "1", "time": 1312950803.96857, "item": "en"},
{"sequence": "1", "time": 1312950804.26057, "item": "eng"},
{"sequence": "1", "time": 1312950804.56057, "item": "engi"},
{"sequence": "1", "time": 1312950804.76057, "item": "engin"},
{"sequence": "1", "time": 1312950805.86057, "item": "engine", "type": "submit"}
]
# [[0, 1337566253.89858, 0.000355720520019531], 6]

以下は補正用の学習データです。

実行例:

load --table event_query --each 'suggest_preparer(_id, type, item, sequence, time, pair_query)'
[
{"sequence": "2", "time": 1312950803.86057, "item": "s"},
{"sequence": "2", "time": 1312950803.96857, "item": "sa"},
{"sequence": "2", "time": 1312950804.26057, "item": "sae"},
{"sequence": "2", "time": 1312950804.56057, "item": "saer"},
{"sequence": "2", "time": 1312950804.76057, "item": "saerc"},
{"sequence": "2", "time": 1312950805.76057, "item": "saerch", "type": "submit"},
{"sequence": "2", "time": 1312950809.76057, "item": "serch"},
{"sequence": "2", "time": 1312950810.86057, "item": "search", "type": "submit"}
]
# [[0, 1337566253.89858, 0.000355720520019531], 8]

以下は提案用の学習データです。

実行例:

load --table event_query --each 'suggest_preparer(_id, type, item, sequence, time, pair_query)'
[
{"sequence": "3", "time": 1312950803.86057, "item": "search engine", "type": "submit"},
{"sequence": "3", "time": 1312950808.86057, "item": "web search realtime", "type": "submit"}
]
# [[0, 1337566253.89858, 0.000355720520019531], 2]

以下は補完例です。

実行例:

suggest --table item_query --column kana --types complete --frequency_threshold 1 --query en
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   {
#     "complete": [
#       [
#         1
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "_score",
#           "Int32"
#         ]
#       ],
#       [
#         "engine",
#         1
#       ]
#     ]
#   }
# ]

以下は補正例です。

実行例:

suggest --table item_query --column kana --types correct --frequency_threshold 1 --query saerch
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   {
#     "correct": [
#       [
#         1
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "_score",
#           "Int32"
#         ]
#       ],
#       [
#         "search",
#         1
#       ]
#     ]
#   }
# ]

以下は提案例です。

実行例:

suggest --table item_query --column kana --types suggest --frequency_threshold 1 --query search
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   {
#     "suggest": [
#       [
#         2
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "_score",
#           "Int32"
#         ]
#       ],
#       [
#         "search engine",
#         1
#       ],
#       [
#         "web search realtime",
#         1
#       ]
#     ]
#   }
# ]

以下は補完・補正・提案を混ぜた例です。

実行例:

suggest --table item_query --column kana --types complete|correct|suggest --frequency_threshold 1 --query search
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   {
#     "suggest": [
#       [
#         2
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "_score",
#           "Int32"
#         ]
#       ],
#       [
#         "search engine",
#         1
#       ],
#       [
#         "web search realtime",
#         1
#       ]
#     ],
#     "complete": [
#       [
#         2
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "_score",
#           "Int32"
#         ]
#       ],
#       [
#         "search",
#         2
#       ],
#       [
#         "search engine",
#         2
#       ]
#     ],
#     "correct": [
#       [
#         1
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "_score",
#           "Int32"
#         ]
#       ],
#       [
#         "search",
#         2
#       ]
#     ]
#   }
# ]

  参考

•   /suggest

•   /reference/executables/groonga-suggest-create-dataset

  table_create

  概要

table_create は現在のデータベースに新しいテーブルを作成します。データを保存したり検索したりするために、1つ以上のテーブルを作成する必要があります。

  構文

table_create には多くの引数があります。必須の引数は name だけで、残りは省略できます。:

table_create name
             [flags=TABLE_HASH_KEY]
             [key_type=null]
             [value_type=null]
             [default_tokenizer=null]
             [normalizer=null]

  使い方

table_create コマンドは新しく永続テーブルを作成します。テーブルの詳細については /reference/tables を参照してください。

  データ保存用テーブルの作成

データ保存用のテーブルにはどの種類のテーブルでも使えます。テーブルの種類については /reference/tables を参照してください。

テーブルの型は TABLE_${TYPE} を flags 引数に指定します。

以下は TABLE_NO_KEY テーブルを使う例です。

実行例:

table_create Logs TABLE_NO_KEY
# [[0, 1337566253.89858, 0.000355720520019531], true]

この table_create コマンドは Logs という名前で TABLE_NO_KEY 型のテーブルを作成します。

キーでレコードを検索しないのであれば、 TABLE_NO_KEY 型のテーブルが適切です。なぜなら、 TABLE_NO_KEY はキーをサポートしていませんが、速くて小さいサイズのテーブルだからです。ログをgroongaのデータベースに保存するという使い方はこのケースです。

キーでレコードを検索したり、カラムからレコードを参照したりする場合は、 TABLE_NO_KEY 型は適していません。全文検索用の語彙表として使うケースはこのケースです。

  語彙表テーブルの作成

語彙表テーブル用のテーブルには TABLE_NO_KEY 以外の型のテーブルを使います。語彙表テーブルはキーをサポートしていないといけませんが、 TABLE_NO_KEY はキーをサポートしていません。

以下は TABLE_PAT_KEY テーブルを作る例です。

実行例:

table_create Lexicon TABLE_PAT_KEY ShortText --default_tokenizer TokenBigram --normalizer NormalizerAuto
# [[0, 1337566253.89858, 0.000355720520019531], true]

この table_create コマンドは以下のテーブルを作成します。

•   このテーブルは Lexicon という名前です。

•   このテーブルは TABLE_PAT_KEY 型のテーブルです。

•   このテーブルのキーは ShortText 型です。

•   このテーブルは正規化されたテキストからトークンを抽出するために TokenBigram トークナイザーを使います。

•   このテーブルはテキストを正規化するために NormalizerAuto ノーマライザーを使います。

    語彙表テーブルには TABLE_PAT_KEY が適切なテーブルの型です。語彙表テーブルは全文検索に使われます。

    全文検索では、あいまい検索をするために前方一致検索を使っています。前方一致検索は TABLE_PAT_KEY と TABLE_DAT_KEY がサポートしています。

    全文検索対象のテキストには大量のトークンが含まれるので、語彙表テーブルのキーも大量になります。大量のキーを格納するテーブルの場合はテーブルのサイズを意識する必要があります。これは、大きなテーブルはそれだけ多くのメモリーを必要とするからです。多くのメモリーが必要になると、ディスクI/Oが発生することもあります。ディスクI/Oが発生すると高速に検索できなくなります。そのため、大量のキーがあるテーブルの場合はテーブルのサイズが重要になります。 TABLE_PAT_KEY は TABLE_DAT_KEY よりもテーブルのサイズが小さいです。

    上記の理由から、 TABLE_PAT_KEY が語彙表テーブルに適したテーブルの型です。

  タグインデックス用テーブルの作成

タグインデックス用のテーブルには TABLE_NO_KEY 以外の型のテーブルを使えます。タグインデックス用のテーブルはキーのサポートが必要ですが、 TABLE_NO_KEY はキーをサポートしていません。

以下は TABLE_HASH_KEY 型のテーブルを作る例です。

実行例:

table_create Ages TABLE_DAT_KEY UInt32
# [[0, 1337566253.89858, 0.000355720520019531], true]

この table_create コマンドは Tags という名前で TABLE_HASH_KEY 型のテーブルを作ります。このテーブルのキーは ShortText 型です。

タグインデックス用のテーブルには TABLE_HASH_KEY あるいは TABLE_DAT_KEY が適切なテーブルの型です。

完全一致でタグを検索する機能だけが必要なら、 TABLE_HASH_KEY が適切です。多くの場合はこのケースです。

もし、前方一致検索機能も必要な場合（例えば、 "gr" というキーワードで "groonga" を検索する場合）は、 TABLE_DAT_KEY が適切です。 TABLE_DAT_KEY はサイズの大きなテーブルですが、タグの数はそれほど多くならないので、サイズは重要ではありません。

  範囲検索用のインデックステーブルの作成

範囲検索用のインデックステーブルには TABLE_PAT_KEY 型と TABLE_DAT_KEY 型を使えます。範囲検索用のインデックステーブルは範囲検索をサポートしている必要がありますが、 TABLE_NO_KEY 型と TABLE_HASH_KEY 型はサポートしていません。

以下は TABLE_DAT_KEY テーブルを作成する例です。

実行例:

table_create Ages TABLE_DAT_KEY UInt32
# [[0, 1337566253.89858, 0.000355720520019531], true]

この table_create コマンドは Ages という名前で TABLE_DAT_KEY 型のテーブルを作成します。このテーブルのキーの型は UInt32 です。

範囲検索用のインデックステーブルには TABLE_PAT_KEY 型と TABLE_DAT_KEY 型が適切なテーブルの型です。

インデックス対象の項目が少なければ、 TABLE_DAT_KEY 型が適切です。前述の例では、年齢（age）用のインデックスがこのケースになります。年齢のインデックスはせいぜい0から100項目くらいにしかなりません。これは、人はそんなに長生きできないからです。

インデックス対象が大量にある場合は、 TABLE_PAT_KEY 型が適切です。なぜなら、 TABLE_PAT_KEY 型は TABLE_DAT_KEY 型よりもサイズが小さいからです。

  引数

このセクションではすべての引数について説明します。

  name

作成するテーブル名を指定します。 name は必ず指定しなければいけません。

利用可能な文字は以下の通りです。

•   0 .. 9 （数字）

•   a .. z （アルファベット。小文字）

•   A .. Z （アルファベット。大文字）

•   # （シャープ）

•   @ （アットマーク）

•   - （ハイフン）

•   _ （アンダースコア）（注: 最初の文字としてアンダースコアを使うことはできません。）

    上記の文字を1つ以上使って名前を決めます。 _name というように、最初の文字に _ を使えないことに注意してください。

  flags

テーブルの型とテーブルをカスタマイズするオプションを指定します。

指定可能なフラグは以下の通りです。
フラグ | 説明
TABLE_NO_KEY | 配列テーブル。
TABLE_HASH_HEY | ハッシュテーブル。
TABLE_PAT_KEY | パトリシアトライ。
TABLE_DAT_KEY | ダブル配列トライ。
KEY_WITH_SIS | 半無限文字列を有効にします。 TABLE_PAT_KEY を使う必要があります。

ノート groonga 2.1.0から KEY_NORMALIZE フラグは非推奨になりました。代わりに、 normalizer オプションに NormalizerAuto を指定してください。

TABLE_${TYPE} フラグのどれか1つを指定します。 TABLE_${TYPE} フラグを2つ以上指定することはできません。例えば、 TABLE_NO_KEY|TABLE_HASH_KEY は不正な指定方法です。

TABLE_PAT_KEY|KEY_WITH_SIS というように、 | （縦棒）で複数のフラグを組み合わせることができます。

それぞれのテーブルの型の違いは /reference/tables を参照してください。

デフォルトのフラグは TABLE_HASH_KEY です。

  key_type

キーの型を指定します。

flags パラメーターに TABLE_HASH_KEY 、 TABLE_PAT_KEY または TABLE_DAT_KEY を指定した場合は、 key_type オプションを指定する必要があります。

型の一覧は /reference/types にあります。

デフォルト値はありません。

  value_type

値の型を指定します。

flags パラメーターに TABLE_NO_KEY 、 TABLE_HASH_KEY または TABLE_PAT_KEY を指定した場合は「値」を使うことができます。「値」の型は固定長でなければいけません。例えば、 UInt32 は使えますが、 ShortText は使えません。この場合は値ではなく、カラムを使ってください。

デフォルト値はありません。

  default_tokenizer

デフォルトトークナイザーを指定します。これは、検索時とデータロード時に使われます。

TABLE_NO_KEY と一緒に default_tokenizer を使うことはできません。これは、 TABLE_NO_KEY をインデックスに使うことができないからです。

全文検索用のインデックスとして使う場合には default_tokenizer を必ず指定しなければいけません。

トークナイザーの一覧は /reference/tokenizers にあります。

デフォルト値はありません。

  normalizer

キーを正規化するために使うノーマライザーを指定します。

TABLE_NO_KEY はキーをサポートしていないので、 TABLE_NO_KEY と normalizer を一緒に指定することはできません。

ノーマライザーの一覧は /reference/normalizers にあります。

デフォルト値はありません。

  戻り値

table_create が成功したときは以下のようにボディは true になります:

[HEADER, true]

table_create が失敗すると、エラーの詳細は HEADER に含まれます。

HEADER については /reference/command/output_format を参照してください。

  参考

•   /reference/tables

•   /reference/commands/column_create

•   /reference/tokenizers

•   /reference/normalizers

•   /reference/command/output_format

  table_list

  名前

table_list - DBに定義されているテーブルをリスト表示

  書式

table_list

  説明

groonga組込コマンドの一つであるtable_listについて説明します。組込コマンドは、groonga実行ファイルの引数、標準入力、またはソケット経由でgroongaサーバにリクエストを送信することによって実行します。

table_listは、DBに定義されているテーブルのリストを表示します。

  引数

ありません。

  返値

  json形式

テーブル名一覧が以下の形式で返却されます。:

[[[テーブル情報名1,テーブル情報型1],...], テーブル情報1,...]

テーブル情報名n テーブル情報n には複数の情報が含まれますが、そこに入る情報がどんな内容かを示す名前を出力します。 情報名は以下の通りです。

id テーブルオブジェクトに割り当てられたID

name テーブル名

path テーブルのレコードを格納するファイル名

flags テーブルのflags属性

domain 主キー値の属する型

range valueが属する型

テーブル情報型n テーブル情報の型を出力します。

テーブル情報n テーブル情報名n で示された情報の配列を出力します。 情報の順序は テーブル情報名n の順序と同じです。

実行例:

table_list
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         "id",
#         "UInt32"
#       ],
#       [
#         "name",
#         "ShortText"
#       ],
#       [
#         "path",
#         "ShortText"
#       ],
#       [
#         "flags",
#         "ShortText"
#       ],
#       [
#         "domain",
#         "ShortText"
#       ],
#       [
#         "range",
#         "ShortText"
#       ],
#       [
#         "default_tokenizer",
#         "ShortText"
#       ],
#       [
#         "normalizer",
#         "ShortText"
#       ]
#     ],
#     [
#       259,
#       "Ages",
#       "/tmp/groonga-databases/commands_table_create.0000103",
#       "TABLE_DAT_KEY|PERSISTENT",
#       "UInt32",
#       null,
#       null,
#       null
#     ],
#     [
#       257,
#       "Lexicon",
#       "/tmp/groonga-databases/commands_table_create.0000101",
#       "TABLE_PAT_KEY|PERSISTENT",
#       "ShortText",
#       null,
#       "TokenBigram",
#       "NormalizerAuto"
#     ],
#     [
#       256,
#       "Logs",
#       "/tmp/groonga-databases/commands_table_create.0000100",
#       "TABLE_NO_KEY|PERSISTENT",
#       null,
#       null,
#       null,
#       null
#     ],
#     [
#       258,
#       "Tags",
#       "/tmp/groonga-databases/commands_table_create.0000102",
#       "TABLE_HASH_KEY|PERSISTENT",
#       "ShortText",
#       null,
#       null,
#       null
#     ]
#   ]
# ]

  table_remove

  名前

table_remove - テーブルの削除

  書式

table_remove name

  説明

groonga組込コマンドの一つであるtable_removeについて説明します。組込コマンドは、groonga実行ファイルの引数、標準入力、またはソケット経由でgroongaサーバにリクエストを送信することによって実行します。

table_removeはテーブルと定義されているカラムを削除します。カラムに付随するインデックスも再帰的に削除されます。

  引数

name
    削除対象のカラムが定義されているテーブルの名前を指定します。

  返値

  json形式

[成功かどうかのフラグ]

成功かどうかのフラグ エラーが生じなかった場合にはtrue、エラーが生じた場合にはfalseを返す。

  例

table_remove Entry
[true]

  データ型

  名前

groonga データ型

  説明

groonga は、格納するデータの型を区別します。

groongaのデータベースでは、テーブルの主キーや、カラムの値はいずれも何らかの型に属します。また通常は、一つのテーブルの中の全てのレコードについて、カラムの値は共通となります。

主キーの型とカラムの型には、groongaで予め定義済みの型か、ユーザが定義する型、またはユーザが定義したテーブルを指定することができます。

主キーの型に他のテーブルを指定する場合は、そのテーブルは、主キーの型となるテーブルのサブセットとなります。

カラムの型に他のテーブルを指定する場合は、そのカラムは、カラムの型となるテーブルの参照キーとなります。

  組込型

以下の型が組込型としてあらかじめ定義されています。

Object 任意のテーブルに属する全てのレコードです。 [1]

Bool ブーリアン型やブール型などと呼ばれる型であり、真偽値を表します。取り得る値はtrueとfalseです。（デフォルト値: false）

/reference/commands/load コマンドで値を格納するときは、false、0、空文字列のいずれかを指定するとfalseになり、それ以外を指定するとtrueになります。

Int8 8bit符号付き整数であり、-128以上127以下の整数を表します。（デフォルト値: 0）

UInt8 8bit符号なし整数であり、0以上255以下の整数を表します。（デフォルト値: 0）

Int16 16bit符号付き整数であり、-32,768以上32,767以下の整数を表します。（デフォルト値: 0）

UInt16 16bit符号なし整数であり、0以上65,535以下の整数を表します。（デフォルト値: 0）

Int32 32bit符号付き整数であり、-2,147,483,648以上2,147,483,647以下の整数を表します。（デフォルト値: 0）

UInt32 32bit符号なし整数であり、0以上4,294,967,295以下の整数を表します。（デフォルト値: 0）

Int64 64bit符号付き整数であり、-9,223,372,036,854,775,808以上9,223,372,036,854,775,807以下の整数を表します。（デフォルト値: 0）

UInt64 64bit符号なし整数であり、0以上18,446,744,073,709,551,615以下の整数を表します。（デフォルト値: 0）

浮動小数点数 IEEE 754形式の倍精度浮動小数点数であり、実数を表します。（デフォルト値: 0.0）

IEEE 754形式の詳細については、 IEEE 754 - Wikipedia や IEEE 754: Standard for Binary Floating-Point を参照してください。

時間 日時を表す型であり、1970年1月1日0時0分0秒からの経過時間を、マイクロ秒単位で64bit符号付き整数により表現します。（デフォルト値: 0）

/reference/commands/load コマンドで値を格納するときは、1970年1月1日0時0分0秒からの経過秒数を指定します。秒単位より詳細な日時を指定するには、小数を使います。

ShortText 4,095バイト以下の文字列を表します。（デフォルト値: ""）

Text 65,535バイト以下の文字列を表します。（デフォルト値: ""）

LongText 2,147,483,647バイト以下の文字列を表します。（デフォルト値: ""）

TokyoGeoPoint 旧日本測地系による経緯度であり、経度と緯度をミリ秒単位で表現した整数の組により表現します。（デフォルト値: 0x0）

度分秒形式でx度y分z秒となる経度・緯度は、(((x * 60) + y) * 60 + z) * 1000という計算式でミリ秒単位へと変換されます。 /reference/commands/load コマンドで値を格納するときは、"ミリ秒単位の経度xミリ秒単位の緯度" もしくは "経度の小数表記x緯度の小数表記" という文字列表現を使って指定します。経度と緯度の区切りとしては、'x' のほかに ',' を使うことができます。

測地系の詳細については、 測地系 - Wikipedia を参照してください。

WGS84GeoPoint 世界測地系（World Geodetic System, WGS 84）による経緯度であり、経度と緯度をミリ秒単位で表現した整数の組により表現します。（デフォルト値: 0x0）

度分秒形式からミリ秒形式への変換方法や /reference/commands/load コマンドにおける指定方法はTokyoGeoPointと同じです。

  型に関する制限事項

  テーブルの主キーに指定できない型

Text型とLongText型については、テーブルの主キーに指定することはできません。

  ベクターとして格納できない型

groongaのカラムは、ある型のベクターを保存することができます。しかし、ShortText, Text, LongTextの３つの型についてはベクターとして保存したり出力したりすることはできますが、検索条件やドリルダウン条件に指定することができません。

テーブル型は、ベクターとして格納することができます。よって、ShortTextのベクターを検索条件やドリルダウン条件に使用したい場合には、主キーがShortText型のテーブルを別途作成し、そのテーブルを型として利用します。 脚注

[1] Object型はv1.2でサポートされます。

  テーブル

  概要

groongaのテーブルはIDとキーの対応を管理します。groongaは4つの種類のテーブルを提供しています。 TABLE_NO_KEY 、 TABLE_HASH_KEY 、 TABLE_PAT_KEY 、 TABLE_DAT_KEY です。

TABLE_NO_KEY 以外のすべてのテーブルは高速なキー→ID検索とID→キー検索の両方をサポートしています。 TABLE_NO_KEY はキーをサポートしていません。 TABLE_NO_KEY はIDだけを管理します。そのため、 TABLE_NO_KEY はID検索もキー検索もサポートしていません。

  特徴

以下はgroongaにあるすべてのテーブルの特性表です。（この表の中では TABLE_ プレフィックスは省略しています。）
 | NO_KEY | HASH_KEY | PAT_KEY | DAT_KEY
データ構造 | 配列 | ハッシュテーブル | パトリシアトライ | ダブル配列トライ
IDサポート | o | o | o | o
キーサポート | x | o | o | o
バリューサポート | o | o | o | x
キー→ID検索速度 o: 速い x: 遅い | - | oo | x | o
更新速度 o: 速い x: 遅い | ooo | o | o | x
サイズ o: 小さい x: 大きい | ooo | o | oo | x
キー変更 | - | x | x | o
共通接頭辞検索 | - | x | o | o
前方一致検索 | - | x | o | o
範囲検索 | - | x | o | o

  TABLE_NO_KEY

TABLE_NO_KEY はとても高速でとても小さいのですが、キーをサポートしていません。キーをサポートしていないテーブルは TABLE_NO_KEY だけです。

TABLE_NO_KEY を全文検索用の語彙表として使うことはできません。これは、語彙表はトークンをキーとして保存する必要があるからです。 TABLE_NO_KEY はログのようにキーのないレコードを管理するテーブルとして有用です。

  TABLE_HASH_KEY

TABLE_HASH_KEY は高速ですが、共通接頭辞検索や前方一致検索といった高度な検索機能をサポートしていません。

TABLE_HASH_KEY はタグ検索のように完全一致検索用のインデックスとして有用です。

  TABLE_PAT_KEY

TABLE_PAT_KEY は、小さく、高度な検索機能もサポートしています。

TABLE_PAT_KEY は全文検索用の語彙表としても有用ですし、範囲検索用のインデックスとしても有用です。

  TABLE_DAT_KEY

TABLE_DAT_KEY は高速でキーの更新もサポートしていますが、サイズが大きいです。大量のレコードを保存する用途には向いていません。キーの更新をサポートしているテーブルは TABLE_DAT_KEY だけです。

TABLE_DAT_KEY はgroongaのデータベース内で使われています。groongaのデータベースは ShortText や TokenBigram 、テーブル名などオブジェクトの名前をオブジェクトのIDに変換する必要があります。さらに、groongaのデータベースはオブジェクト名の変更もサポートする必要があります。これらの機能は TABLE_DAT_KEY で実現されています。オブジェクト数は小さいので TABLE_DAT_KEY のサイズが大きいというデメリットは無視できます。

  レコードID

レコードIDは自動的に割り当てられます。明示的に割り当てるレコードIDを指定することはできません。

削除されたレコードのレコードIDは再利用される可能性があります。

妥当なレコードIDの範囲は1から268435455までです。（1も268435455も妥当なIDです。）

  永続テーブルと一時テーブル

テーブルは永続テーブルまたは一時テーブルです。

  永続テーブル

永続テーブルは名前がついていてデータベースに登録されています。永続テーブルの中のレコードはテーブルやデータベースを閉じた後でも消えません。

永続テーブルは /reference/commands/table_create コマンドで作成します。

  一時テーブル

一時テーブルには名前がありません。一時テーブルのレコードはテーブルを閉じると削除されます。一時テーブルは検索結果やソート結果、グループ（ドリルダウン）結果などを格納するために使われています。検索結果とグループ結果には TABLE_HASH_KEY が使われています。ソート結果には TABLE_NO_KEY が使われています。

  制限

最大レコード数は268435455です。1つのテーブルに268435456以上のレコードを追加できません。

最大キーサイズは4096バイトです。4097バイト以上の大きいキーは使うことができません。4097バイト以上の大きなサイズのデータはキーではなくカラムに保存してください。 Text と LargeText 型は4097バイト以上の大きさのサイズのデータをサポートしています。

キーサイズの合計の最大値は4GiBです。キーサイズの合計が4GiBを超える場合は、テーブルを分割したり、データベースを分割したり（シャーディング）、それぞれのキーのサイズを減らしてください。

  参考

•   /reference/commands/table_create

  ノーマライザー

  概要

groongaには正規化をするノーマライザーモジュールがあります。これはテキストをトークナイズするときとテーブルのキーを保存するときに使われます。例えば、正規化をした後は A と a は同じ文字として扱われます。

ノーマライザーモジュールはプラグインとして追加できます。ノーマライザープラグインをgroongaに追加することでテキストの正規化方法をカスタマイズできます。

ノーマライザーモジュールはテーブルに関連付いています。テーブルは0個か1個のノーマライザーモジュールを持つことができます。 /reference/commands/table_create の table-create-normalizer オプションでテーブルにノーマライザーオプションを関連付けることができます。

以下は NormalizerAuto ノーマライザーモジュールを使う table_create の例です。

実行例:

table_create Dictionary TABLE_HASH_KEY ShortText --normalizer NormalizerAuto
# [[0, 1337566253.89858, 0.000355720520019531], true]

ノート groonga 2.0.9以前には table_create に --normalizer オプションはありません。代わりに KEY_NORMALIZE フラグを使っていました。

    groonga 2.1.0以降で古いデータベースを開くことができます。ここでいう古いデータベースとはgroonga 2.0.9以前で作ったデータベースということです。しかし、一度新しいgroongaで開いたデータベースを2.0.9以前のgroongaで開くことはできません。一度 groonga 2.1.0以降のgroongaでデータベースを開くと、 KEY_NORMALIZE フラグ情報がノーマライザー情報に変換されます。そのため、2.0.9以前のgroongaは、一度groonga 2.1.0以降で開いたデータベース内から KEY_NROMALIZE フラグの情報を見つけることができません。

ノーマライザーモジュールを持っているテーブルのキーは正規化されます。

実行例:

load --table Dictionary
[
{"_key": "Apple"},
{"_key": "black"},
{"_key": "COLOR"}
]
# [[0, 1337566253.89858, 0.000355720520019531], 3]
select Dictionary
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         3
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ]
#       ],
#       [
#         1,
#         "apple"
#       ],
#       [
#         2,
#         "black"
#       ],
#       [
#         3,
#         "color"
#       ]
#     ]
#   ]
# ]

NormalizerAuto ノーマライザーはテキストを小文字に正規化します。例えば、 "Apple" は "apple" に正規化され、 "black" は "blank" に正規化され、 "COLOR" は "color" に正規化されます。

テーブルが全文検索用の語彙表の場合、トークナイズされたトークンは正規化されます。なぜなら、トークンはテーブルのキーとして保存されるからです。テーブルのキーは前述のように正規化されます。

  組み込みノーマライザー

以下は組み込みのノーマライザーのリストです。

•   NormalizerAuto

•   NormalizerNFKC51

  NormalizerAuto

通常は NormalizerAuto ノーマライザーを使うべきです。 NormalizerAuto はgroonga 2.0.9以前で使っていたノーマライザーと同じものです。2.0.9以前のgroongaの table_create の KEY_NORMALIZE フラグは、2.1.0以降のgroongaの table_create の --normalizer NormalizerAuto と同じです。

NormalizerAuto はすべてのエンコーディングに対応しています。UTF-8でエンコードされたテキストにはUnicodeのNFKC（Normalization Form Compatibility Composition）を使います。他のエンコーディング用にはエンコーディング毎に独自の正規化をします。これらの独自の正規化の結果はNFKCでの結果と似たものになります。

例えば、半角カタカナ（例えば「ｶ」: U+FF76 HALFWIDTH KATAKANA LETTER KA） + 半角カタカナの濁点（「ﾞ」: U+FF9E HALFWIDTH KATAKANA VOICED SOUND MARK）は濁点付きの全角カタカナ（「ガ」: U+30AC KATAKANA LETTER GA）に正規化されます。前者は2文字ですが、後者は1文字です。

以下は NormalizerAuto ノーマライザーを使う例です。

実行例:

table_create NormalLexicon TABLE_HASH_KEY ShortText --normalizer NormalizerAuto
# [[0, 1337566253.89858, 0.000355720520019531], true]

  NormalizerNFKC51

NormalizerNFKC51 はUnicode 5.1用のUnicode NFKC（Normalization Form Compatibility Composition）を使ってテキストを正規化します。UTF-8エンコーディングのみをサポートしています。

通常、 NormalizerNFKC51 を明示的に使う必要はありません。代わりに NormalizerAuto を使ってください。

以下は NormalizerNFKC51 ノーマライザーを使う例です。

実行例:

table_create NFKC51Lexicon TABLE_HASH_KEY ShortText --normalizer NormalizerNFKC51
# [[0, 1337566253.89858, 0.000355720520019531], true]

  追加のノーマライザー

groonga-normalizer-mysql パッケージで提供される追加のノーマライザーのリストです。

•   NormalizerMySQLGeneralCI

    groonga-normalizer-mysql はgroongaのプラグインです。MySQL互換のノーマライザーを提供します。ノーマライザー NormalizerMySQLGeneralCI に対応するのは utf8mb4_general_ci です。

    事前に normalizers/mysql プラグインを登録する必要があります。

    実行例:

    register normalizers/mysql
    # [[0, 1337566253.89858, 0.000355720520019531], true]

    以下は NormalizerMySQLGeneralCI ノーマライザーを使う例です。

    実行例:

    table_create MySQLGeneralLexicon TABLE_HASH_KEY ShortText --normalizer NormalizerMySQLGeneralCI
    # [[0, 1337566253.89858, 0.000355720520019531], true]

  参考

•   /reference/commands/table_create

  Tokenizers

TODO: Write me.

  クエリー展開オブジェクト一覧

  QueryExpanderTSV

  概要

QueryExpanderTSV はクエリー展開プラグインです。同義語はTSV（データをタブで区切るファイルフォーマット）ファイルから読み込みます。このプラグインは組み込みのクエリー展開機能よりも機能が少ないです。例えば、単語の正規化をサポートしていません。しかし、TSVファイルで同義語を管理できるためこちらの方が使いやすいかもしれません。TSVファイルなのでExcelなどの表計算ソフトで同義語を編集できます。組み込みのクエリー展開機能では、groongaのテーブルとして同義語を管理します。

  インストール

QueryExpanderTSV を使う前に query_expanders/tsv をプラグインとして登録します:

register query_expanders/tsv

  使い方

select コマンドに --query_expansion QueryExpanderTSV パラメーターを追加します:

select --query "QUERY" --query_expansion QueryExpanderTSV

QUERY 内に登録済みの同義語がある場合はそれらが展開されます。例えば、以下の同義語があるとします。
単語 | 同義語1 | 同義語2
groonga | groonga | Senna
mroonga | mroonga | groonga MySQL

この表は、 単語 の同義語は 同義語1 と 同義語2 という意味です。例えば、 groonga の同義語は groonga と Senna です。また、 mroonga の同義語は mroonga と groonga MySQL です。

クエリーが groonga のときのクエリー展開の例です:

select --query "groonga" --query_expansion QueryExpanderTSV

上記のコマンドは以下のコマンドと同じ意味です:

select --query "groonga OR Senna" --query_expansion QueryExpanderTSV

クエリーが mroonga search のときのクエリー展開の例です:

select --query "mroonga search" --query_expansion QueryExpanderTSV

上記のコマンドは以下のコマンドと同じ意味です:

select --query "(mroonga OR (groonga MySQL)) search" --query_expansion QueryExpanderTSV

登録されている単語だけ（ここでは groonga と mroonga ）クエリー展開されて、登録されていない単語（ここでは search ）はクエリー展開されていないことが大事なポイントです。また、再帰的にクエリー展開しません。クエリー展開した結果の (mroonga OR (groonga MySQL)) の中に groonga がありますが、これは展開されません。

通常、同義語の中に 単語 自身も含める必要があります。例えば、 groonga と mroonga が同義語の中に含まれています。もし、 単語 自身を無視したい場合は同義語の中に 単語 を含めないでください。例えば、クエリー展開機能をスペル訂正機能として使う場合は、以下のような同義語を使ってください。
単語 | 同義語
gronga | groonga

単語 の gronga には誤字があります。 o がひとつ足りません。 同義語 の groonga が正しい単語です。

スペル訂正機能としてクエリー展開機能を使う例です:

select --query "gronga" --query_expansion QueryExpanderTSV

上記のコマンドは以下のコマンドと同じ意味です:

select --query "groonga" --query_expansion QueryExpanderTSV

前者のコマンドは --query の値に誤字がありますが、後者のコマンドは誤字がありません。

  TSVファイル

同義語はTSVフォーマットのファイルで定義します。このセクションでは定義方法について説明します。

  場所

TSVファイルのファイル名は synonyms.tsv で、設定ディレクトリに置かなければいけません。例えば、 /etc/groonga/synonyms.tsv がTSVファイルの場所になります。場所はビルド時に決まります。

環境変数 GRN_QUERY_EXPANDER_TSV_SYNONYMS_FILE を指定することで実行時に場所を変更することもできます:

% env GRN_QUERY_EXPANDER_TSV_SYNONYMS_FILE=/tmp/synonyms.tsv groonga

上述のコマンドでは /tmp/synonyms.tsv ファイルが使われます。

  フォーマット

TSVファイル内に0個以上の同義語を定義することができます。1行につき 単語 と 同義語リスト のペアを定義します。 --query の値の中にでてきた 単語 は 同義語リスト に展開されます。 同義語リスト は OR でまとめます。例えば、同義語リスト groonga と Senna は groonga OR Senna と展開されます。

最初のカラムが 単語 で、残りのカラムが 単語 の 同義語リスト になります。以下は、 単語 が groonga で、 同義語リスト が groonga と synonyms の例です。 (TAB) はタブ文字（ U+0009 ）という意味です:

groonga(TAB)groonga(TAB)Senna

コメント行をサポートしています。 # から始まる行は無視します。以下はコメント行の例です。 groonga とある行はコメント行として無視されます:

#groonga(TAB)groonga(TAB)Senna
mroonga(TAB)mroonga(TAB)groonga MySQL

  制限

同義語を再読み込みするにはgroongaを再起動する必要があります。TSVファイルはプラグイン読み込み時に一度だけ読み込みます。

  参考

•   query-expansion

  疑似カラム (pseudo_column)

  名前

疑似カラム

  説明

groongaのデータベースで作成したテーブルには、いくつかのカラムが自動的に定義されます。

これらのカラムはいずれもアンダースコア('_')で始まる名前が付与されます。定義される疑似カラムは、テーブルの種類によって異なります。

_id レコードに付与される一意な番号です。全てのテーブルに定義されます。値の範囲は1〜1073741824の整数で、通常はレコードを追加した順に1ずつ加算されます。_idの値は不変で、レコードが存在する限り変更することはできません。ただし、削除されたレコードの_idの値は再利用されます。

_key レコードの主キー値を表します。主キーを持つテーブルのみに定義されます。主キー値はテーブルの中で一意であり、変更することはできません。

_value レコードの値を表します。value_typeを指定したテーブルのみに定義されます。自由に変更可能です。

_score 各レコードのスコア値を表します。検索結果として生成されたテーブルのみに定義されます。

検索処理を実行する過程で値が設定されますが、自由に変更可能です。

_nsubrecs 主キーの値が同一であったレコードの件数を表します。検索結果として生成されたテーブルのみに定義されます。グループ化(drilldown)処理を実行すると、グループ化前のテーブルにおいて、グループ化キーの値が同一であったレコードの件数が、グループ化処理の結果を格納するテーブルの_nsubrecsに記録されます。

  grn_expr

grn_exprは特定の条件にマッチするレコードを検索したり、データベースを操作するオブジェクトです。 ぐるんしき と読みます。（由来は「groongaの式」。）

データベースからレコードを検索する条件は条件式を集合演算で結合して表現できます。例えば、条件式には 等価条件式 や 小なり条件式 などがあります。集合演算には 積（AND） 、 和（OR） 、 差（NOT） などがあります。gnr_exprはこれらの条件を使ってレコードを検索します。類似文書検索や近傍検索などといった高度な検索もgrn_exprで実行できます。柔軟な全文検索も実行できます。例えば、特定の単語にマッチしたときのヒットスコアを調整したり、検索結果数によって検索漏れの少ないアルゴリズムで再検索し、再現率を向上するといったことも実現できます。

grn_exprを作る方法は3つあります:

•   /reference/grn_expr/query_syntax の文字列をパースする。

•   /reference/grn_expr/script_syntax の文字列をパースする。

•   grn_expr関連のAPIを呼ぶ。

    /reference/grn_expr/query_syntax は一般的なインターネット検索サイトにある検索フォーム用の構文です。シンプルで使いやすいですが、制限があります。 /reference/grn_expr/query_syntax では実行できない条件式や集合演算があります。 /reference/grn_expr/query_syntax は /reference/commands/select の query オプションで指定する検索条件で使えます。

    /reference/grn_expr/script_syntax はECMAScriptに似た構文です。 /reference/grn_expr/script_syntax ではすべての条件式と集合演算を使えます。 /reference/grn_expr/script_syntax は /reference/commands/select の filter オプションで指定する検索条件や scorer オプションで指定する式で使えます。

    groongaをライブラリとして使うと、grn_expr関連のAPIを呼び出してgrn_exprを作ることができます。 /reference/grn_expr/script_syntax のように、APIを呼び出すと全ての機能を使えます。grn_exprを作る構文を新しく作るときにはAPIが便利です。APIは rroonga というgroongaのRubyバインディングで使われています。rroongaでは文字列をパースするのではなく、Rubyの構文を使ってgrn_exprを作ることができます。

  クエリー構文

クエリー構文は一般的なWebの検索フォームで検索条件を指定するための構文です。Googleの検索フォームで使われている構文に似ています。例えば、 word1 word2 は word1 と word2 の両方の単語を含んだレコードを検索するという意味です。 word1 OR word2 は word1 または word2 のどちらかの単語を含んだレコードを検索します。

クエリー構文は 条件式 と 結合式 と 代入式 から成ります。通常、 代入式 は考えなくてよいです。なぜなら、 代入式 は /reference/commands/select の --query オプションでは無効になっているからです。groongaをライブラリとして使ったときは、クエリー構文のパーサーのオプションをカスタマイズすることで 代入式 を有効にすることができます。

条件式 は条件を指定します。 結合式 は1つ以上の 条件式 、 結合式 、 代入式 から成ります。 代入式 はカラムに値を代入します。

  サンプルデータ

使い方を示すために使うスキーマ定義とサンプルデータは以下の通りです。

実行例:

table_create Entries TABLE_PAT_KEY ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Entries content COLUMN_SCALAR Text
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Entries n_likes COLUMN_SCALAR UInt32
# [[0, 1337566253.89858, 0.000355720520019531], true]
table_create Terms TABLE_PAT_KEY|KEY_NORMALIZE ShortText --default_tokenizer TokenBigram
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Terms entries_key_index COLUMN_INDEX|WITH_POSITION Entries _key
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Terms entries_content_index COLUMN_INDEX|WITH_POSITION Entries content
# [[0, 1337566253.89858, 0.000355720520019531], true]
load --table Entries
[
{"_key":    "The first post!",
 "content": "Welcome! This is my first post!",
 "n_likes": 5},
{"_key":    "Groonga",
 "content": "I started to use groonga. It's very fast!",
 "n_likes": 10},
{"_key":    "Mroonga",
 "content": "I also started to use mroonga. It's also very fast! Really fast!",
 "n_likes": 15},
{"_key":    "Good-bye Senna",
 "content": "I migrated all Senna system!",
 "n_likes": 3},
{"_key":    "Good-bye Tritonn",
 "content": "I also migrated all Tritonn system!",
 "n_likes": 3}
]
# [[0, 1337566253.89858, 0.000355720520019531], 5]

ブログエントリ用の Entries テーブルがあります。各エントリはタイトルと内容と「いいね！」数を持っています。タイトルは Entries のキーとします。内容は Entries.content カラムの値とします。「いいね！」数は Entries.n_likes カラムの値とします。

Entries._key カラムと Entries.content カラムには TokenBigram トークナイザーを使ったインデックスを作成します。そのため、 Entries._key と Entries.content は両方とも全文検索できます。

これで例を示すためのスキーマとデータの準備ができました。

  エスケープ

クエリー構文には特別な文字があります。特別な文字それ自体を使うためには文字の前に \ をつけてエスケープしなければいけません。例えば、 " は特別な文字です。これは \" というようにエスケープします。

以下が特別な文字のリストです:

•   [space] （ [backquote][space] とエスケープする。）（ [space] をASCIIで言えば0x20の空白文字に置き換えて、 [backquote] を \\ に置き換えてください。）

•   " （ \" とエスケープする。）

•   ' （ \' とエスケープする。）

•   ( （ \( とエスケープする。）

•   ) （ \) とエスケープする。）

•   \ （ \\ とエスケープする。）

    エスケープする代わりにクォートすることもできます。クォート構文は "..." または '...' です。 "..." クォート構文中では " を \" にエスケープする必要があります。 '...' クォート構文中では ' を \' にエスケープする必要があります。例えば、 Alice's brother (Bob) は "Alice's brother (Bob)" あるいは 'Alice\'s brother (Bob)' とクォートします。

  条件式

以下は利用可能な条件式の一覧です。

  全文検索条件

構文は keyword です。

全文検索条件 はデフォルトのマッチカラムに対して全文検索するという条件を指定します。マッチカラムとは全文検索対象のカラムのことです。

全文検索に使うデフォルトのマッチカラムを指定する必要があります。マッチカラムは /reference//commands/select の --match_columns オプションで指定します。デフォルトのマッチカラムを指定していない場合、この条件式は失敗します。

この条件式は keyword で全文検索をします。 keyword には空白を含めることはできません。 search keyword というように空白を含んでいる場合は、 search と keyword という2つの全文検索条件を指定したことになります。もし、キーワードに空白を含めたい場合は以下で説明する フレーズ検索条件 を使ってください。

以下は簡単な使用例です。

実行例:

select Entries --match_columns content --query fast
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         2,
#         "Groonga",
#         "I started to use groonga. It's very fast!",
#         10
#       ],
#       [
#         3,
#         "Mroonga",
#         "I also started to use mroonga. It's also very fast! Really fast!",
#         15
#       ]
#     ]
#   ]
# ]

この式は content カラムの値に fast という単語を含んでいるレコードにマッチします。

content カラムはデフォルトのマッチカラムです。

  フレーズ検索条件

構文は "search keyword" です。

フレーズ検索条件 はデフォルトのマッチカラムに対してフレーズ検索するという条件を指定します。

全文検索に使うデフォルトのマッチカラムを指定する必要があります。マッチカラムは /reference//commands/select の --match_columns オプションで指定します。デフォルトのマッチカラムを指定していない場合、この条件式は失敗します。

この条件式は search keyword でフレーズ検索をします。フレーズ検索は search と keyword がこの順番で隣接して含まれているレコードにマッチします。つまり、 Put a search keyword in the form にはマッチしますが、 Search by the keyword や There is a keyword. Search by it! にはマッチしません。

以下は簡単な使用例です。

実行例:

select Entries --match_columns content --query '"I started"'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         2,
#         "Groonga",
#         "I started to use groonga. It's very fast!",
#         10
#       ]
#     ]
#   ]
# ]

この式は content カラムの値に I started というフレーズを含んでいるレコードにマッチします。 I also started にはマッチしません。これは I と started が隣接していないからです。

content カラムはデフォルトのマッチカラムです。

  全文検索条件（マッチカラム指定あり）

構文は column:@keyword です。

これは 全文検索条件 と似ていますが、デフォルトのマッチカラムは必要ありません。全文検索用のマッチカラムは /reference/commands/select の --match_columns オプションではなく column: で指定します。

この条件式は異なったカラムに対して複数の全文検索をしたい場合に便利です。 --match_columns オプションで指定するデフォルトのマッチカラムは複数回指定することができません。2つめのマッチカラムを指定するためにはこの条件式を使う必要があります。

全文検索条件 と 全文検索条件（マッチカラム指定あり） の違いは高度なマッチカラムをサポートしているかどうかです。 全文検索条件 は高度なマッチカラムをサポートしていますが、 全文検索条件（マッチカラム指定あり） はサポートしていません。高度なマッチカラムには以下の機能があります:

•   重みをサポートしている。

•   複数のカラムを指定できる。

•   マッチカラムとしてインデックスカラムを使える。

    これらについては /reference/commands/select の --match_columns オプションを参照してください。

    以下は簡単な使用例です。

    実行例:

    select Entries --query content:@fast
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         2
    #       ],
    #       [
    #         [
    #           "_id",
    #           "UInt32"
    #         ],
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "content",
    #           "Text"
    #         ],
    #         [
    #           "n_likes",
    #           "UInt32"
    #         ]
    #       ],
    #       [
    #         2,
    #         "Groonga",
    #         "I started to use groonga. It's very fast!",
    #         10
    #       ],
    #       [
    #         3,
    #         "Mroonga",
    #         "I also started to use mroonga. It's also very fast! Really fast!",
    #         15
    #       ]
    #     ]
    #   ]
    # ]

    この式は content カラムの値に fast という単語を含んでいるレコードにマッチします。

  フレーズ検索条件（マッチカラム指定あり）

構文は column:@"search keyword" です。

これは フレーズ検索条件 に似ていますが、デフォルトのマッチカラムは必要ありません。フレーズ検索用のマッチカラムは /reference/commands/select の --match_columns オプションではなく column: で指定します。

フレーズ検索条件 と フレーズ検索条件（マッチカラム指定あり） は 全文検索条件 と 全文検索条件（マッチカラム指定あり） の関係と似ています。 フレーズ検索条件 は高度なマッチカラムをサポートしていますが、 フレーズ検索条件（マッチカラム指定あり） はサポートしていません。高度なマッチカラムについては 全文検索条件（マッチカラム指定あり） を参照してください。

以下は簡単な使用例です。

実行例:

select Entries --query 'content:@"I started"'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         2,
#         "Groonga",
#         "I started to use groonga. It's very fast!",
#         10
#       ]
#     ]
#   ]
# ]

この式は content カラムの値に I started というフレーズを含んでいるレコードにマッチします。 I also started にはマッチしません。これは I と started が隣接していないからです。

  前方一致検索条件

構文は column:^value または value* です。

この条件式は value で前方一致検索をします。前方一致検索は value で始まる単語を含むレコードを検索します。

カラムの値を高速に前方一致検索できます。ただし、そのカラムにはインデックスを作成し、そのインデックス用のテーブルをパトリシアトライ（ TABLE_PAT_KEY ）またはダブル配列トライ（ TABLE_DAT_KEY ）にしなければいけません。あるいは、パトリシアトライテーブルまたはダブル配列テーブルの _key も高速に前方一致検索できます。 _key にインデックスを作成する必要はありません。

他の種類のテーブルでも前方一致検索を使えますがレコード全件を処理します。レコード数が少ない場合には問題ありませんが、レコード数が多いと時間がかかります。

全文検索条件 や フレーズ検索条件 と異なり、デフォルトのマッチカラムは必要ありません。

以下は簡単な使用例です。

実行例:

select Entries --query '_key:^Goo'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         5,
#         "Good-bye Tritonn",
#         "I also migrated all Tritonn system!",
#         3
#       ],
#       [
#         4,
#         "Good-bye Senna",
#         "I migrated all Senna system!",
#         3
#       ]
#     ]
#   ]
# ]

この式は _key カラムの値が Goo で始まる単語を含むレコードにマッチします。この式には Good-bye Senna と Good-bye Tritonn がマッチします。

  後方一致検索条件

構文は column:$value です。

この条件式は value で後方一致検索します。後方一致検索は value で終わる単語を含むレコードを検索します。

カラムの値を高速に後方一致検索できます。ただし、そのカラムにはインデックスを作成し、そのインデックス用のテーブルを KEY_WITH_SIS フラグ付きのパトリシアトライテーブル（ TABLE_PAT_KEY ）にしなければいけません。 KEY_WITH_SIS フラグ付きのパトリシアトライテーブル（ TABLE_PAT_KEY ）の _key 擬似カラムの値も高速に後方一致検索できます。 _key にはインデックスを作成する必要はありません。 _key ベースの高速な後方一致検索よりもカラムベースの高速な後方一致検索を使うことをおすすめします。 _key ベースの高速な後方一致検索は自動的に登録された部分文字列も返ってきます。（TODO: 後方一致検索に関するドキュメントを書いてここからリンクを張る。）

ノート 高速な後方一致検索は日本語のひらがななど非ASCII文字にしか使えません。ASCII文字には高速な後方一致検索を使えません。

後方一致検索は他の種類のテーブルもしくはパトリシアトライを KEY_WITH_SIS フラグなしで使用しているテーブルに対しても使えますが、レコード全件を処理します。レコード数が少ない場合には問題ありませんが、レコード数が多いと時間がかかります。

全文検索条件 や フレーズ検索条件 と異なり、デフォルトのマッチカラムは必要ありません。

簡単な例です。ASCII文字ではない文字である日本語のひらがなに対して高速な後方一致検索をしています。

実行例:

table_create Titles TABLE_NO_KEY
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Titles content COLUMN_SCALAR ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
table_create SuffixSearchTerms TABLE_PAT_KEY|KEY_WITH_SIS ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create SuffixSearchTerms index COLUMN_INDEX Titles content
# [[0, 1337566253.89858, 0.000355720520019531], true]
load --table Titles
[
{"content": "ぐるんが"},
{"content": "むるんが"},
{"content": "せな"},
{"content": "とりとん"}
]
# [[0, 1337566253.89858, 0.000355720520019531], 4]
select Titles --query 'content:$んが'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "content",
#           "ShortText"
#         ]
#       ],
#       [
#         2,
#         "むるんが"
#       ],
#       [
#         1,
#         "ぐるんが"
#       ]
#     ]
#   ]
# ]

この式は content カラムの値が んが で終わるレコードにマッチします。この場合は ぐるんが と むるんが にマッチします。

  等価条件

構文は column:value です。

column の値が value と等しいレコードにマッチします。

全文検索条件 や フレーズ検索条件 と異なり、デフォルトのマッチカラムは必要ありません。

以下は簡単な使用例です。

実行例:

select Entries --query _key:Groonga
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         2,
#         "Groonga",
#         "I started to use groonga. It's very fast!",
#         10
#       ]
#     ]
#   ]
# ]

この式は _key カラムの値が Groonga のレコードにマッチします。

  不等価条件

構文は column:!value です。

column の値が value と等しくないレコードにマッチします。

全文検索条件 や フレーズ検索条件 と異なり、デフォルトのマッチカラムは必要ありません。

以下は簡単な使用例です。

実行例:

select Entries --query _key:!Groonga
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         4
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         4,
#         "Good-bye Senna",
#         "I migrated all Senna system!",
#         3
#       ],
#       [
#         5,
#         "Good-bye Tritonn",
#         "I also migrated all Tritonn system!",
#         3
#       ],
#       [
#         3,
#         "Mroonga",
#         "I also started to use mroonga. It's also very fast! Really fast!",
#         15
#       ],
#       [
#         1,
#         "The first post!",
#         "Welcome! This is my first post!",
#         5
#       ]
#     ]
#   ]
# ]

この式は _key カラムの値が Groonga ではないレコードにマッチします。

  小なり条件

構文は column:<value です。

column の値が value 未満のレコードにマッチします。

column の型が Int32 などの数値型の場合、 column の値と value は数値として比較します。もし、 column の型が ShortText のような文字列型の場合は column の値と value はビット列として比較します。

全文検索条件 や フレーズ検索条件 と異なり、デフォルトのマッチカラムは必要ありません。

以下は簡単な使用例です。

実行例:

select Entries --query n_likes:<10
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         3
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         4,
#         "Good-bye Senna",
#         "I migrated all Senna system!",
#         3
#       ],
#       [
#         5,
#         "Good-bye Tritonn",
#         "I also migrated all Tritonn system!",
#         3
#       ],
#       [
#         1,
#         "The first post!",
#         "Welcome! This is my first post!",
#         5
#       ]
#     ]
#   ]
# ]

この式は n_likes カラムの値が 10 より小さいレコードにマッチします。

  大なり条件

構文は column:>value です。

column の値が value より大きいレコードにマッチします。

column の型が Int32 などの数値型の場合、 column の値と value は数値として比較します。もし、 column の型が ShortText のような文字列型の場合は column の値と value はビット列として比較します。

全文検索条件 や フレーズ検索条件 と異なり、デフォルトのマッチカラムは必要ありません。

以下は簡単な使用例です。

実行例:

select Entries --query n_likes:>10
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         3,
#         "Mroonga",
#         "I also started to use mroonga. It's also very fast! Really fast!",
#         15
#       ]
#     ]
#   ]
# ]

この式は n_likes カラムの値が 10 より大きいレコードにマッチします。

  以下条件

構文は column:<=value です。

column の値が value 以下のレコードにマッチします。

column の型が Int32 などの数値型の場合、 column の値と value は数値として比較します。もし、 column の型が ShortText のような文字列型の場合は column の値と value はビット列として比較します。

全文検索条件 や フレーズ検索条件 と異なり、デフォルトのマッチカラムは必要ありません。

以下は簡単な使用例です。

実行例:

select Entries --query n_likes:<=10
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         4
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         4,
#         "Good-bye Senna",
#         "I migrated all Senna system!",
#         3
#       ],
#       [
#         5,
#         "Good-bye Tritonn",
#         "I also migrated all Tritonn system!",
#         3
#       ],
#       [
#         2,
#         "Groonga",
#         "I started to use groonga. It's very fast!",
#         10
#       ],
#       [
#         1,
#         "The first post!",
#         "Welcome! This is my first post!",
#         5
#       ]
#     ]
#   ]
# ]

この式は n_likes カラムの値が 10 以下のレコードにマッチします。

  以上条件

構文は column:>=value です。

column の値が value 以上のレコードにマッチします。

column の型が Int32 などの数値型の場合、 column の値と value は数値として比較します。もし、 column の型が ShortText のような文字列型の場合は column の値と value はビット列として比較します。

全文検索条件 や フレーズ検索条件 と異なり、デフォルトのマッチカラムは必要ありません。

以下は簡単な使用例です。

実行例:

select Entries --query n_likes:>=10
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         2,
#         "Groonga",
#         "I started to use groonga. It's very fast!",
#         10
#       ],
#       [
#         3,
#         "Mroonga",
#         "I also started to use mroonga. It's also very fast! Really fast!",
#         15
#       ]
#     ]
#   ]
# ]

この式は n_likes カラムの値が 10 以上のレコードにマッチします。

  結合式

以下は利用可能な結合式のリストです。

  論理和

構文は a OR b です。

a と b は条件式または結合式または代入式です。

a と b のうち少なくともひとつの式がマッチすれば a OR b はマッチします。

以下は簡単な使用例です。

実行例:

select Entries --query 'n_likes:>10 OR content:@senna'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         3,
#         "Mroonga",
#         "I also started to use mroonga. It's also very fast! Really fast!",
#         15
#       ],
#       [
#         4,
#         "Good-bye Senna",
#         "I migrated all Senna system!",
#         3
#       ]
#     ]
#   ]
# ]

この式は n_likes カラムの値が 10 より大きいか content カラムの値に senna という単語を含んでいるレコードにマッチします。

  論理積

構文は a + b です。あるいは単に a b と書くこともできます。

a と b は条件式または結合式または代入式です。

a と b の両方にマッチすれば a + b はマッチします。

+a というように最初の式に + を指定することもできます。この場合は + は単に無視されます。

以下は簡単な使用例です。

実行例:

select Entries --query 'n_likes:>=10 + content:@groonga'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         2,
#         "Groonga",
#         "I started to use groonga. It's very fast!",
#         10
#       ]
#     ]
#   ]
# ]

この式は n_likes カラムの値が 10 以上で content カラムの値に groonga という単語を含むレコードにマッチします。

  論理否定

構文は a - b です。

a と b は条件式または結合式または代入式です。

a にマッチして b にマッチしなければ、 a - b はマッチします。

-a というように最初の式に - を指定することはできません。この場合は構文エラーになります。

以下は簡単な使用例です。

実行例:

select Entries --query 'n_likes:>=10 - content:@groonga'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         3,
#         "Mroonga",
#         "I also started to use mroonga. It's also very fast! Really fast!",
#         15
#       ]
#     ]
#   ]
# ]

この式は n_likes カラムの値が 10 以上で content カラムの値に groonga という単語を含まないレコードにマッチします。

  グループ化

構文は (...) です。 ... は空白区切りの式のリストです。

(...) は1つ以上の式をグループ化します。グループ化された式は1つの式として処理されます。 a b OR c は a と b の両方がマッチするか、 c がマッチすれば式全体がマッチする、という意味になります。 a (b OR c) は a がマッチして b と c はどちらか一方がマッチすれば式全体がマッチする、という意味になります。

以下は簡単な使用例です。

実行例:

select Entries --query 'n_likes:<5 content:@senna OR content:@fast'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         3
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         4,
#         "Good-bye Senna",
#         "I migrated all Senna system!",
#         3
#       ],
#       [
#         2,
#         "Groonga",
#         "I started to use groonga. It's very fast!",
#         10
#       ],
#       [
#         3,
#         "Mroonga",
#         "I also started to use mroonga. It's also very fast! Really fast!",
#         15
#       ]
#     ]
#   ]
# ]
select Entries --query 'n_likes:<5 (content:@senna OR content:@fast)'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         4,
#         "Good-bye Senna",
#         "I migrated all Senna system!",
#         3
#       ]
#     ]
#   ]
# ]

最初の式はグループ化していません。この式は n_likes:<5 と content:@senna の両方がマッチするか content:@fast がマッチするレコードにマッチします。

2番目の式はグループ化しています。この式は n_likes:<5 にマッチして、 content:@senna と content:@fast は少なくともどちらか一方にマッチするレコードにマッチします。

  代入式

このセクションは高度なユーザー向けです。それは、代入式は /reference/commands/select の --query オプションではデフォルトでは無効になっているからです。代入式を有効にするには --query_flags オプションに ALLOW_COLUMN|ALLOW_UPDATE を指定してください。

クエリー構文における代入式にはいくつか制限があります。代入にはクエリー構文の代りに /reference/grn_expr/script_syntax を使ってください。

代入式の構文は1つだけです。 column:=value となります。

value は column に代入されます。 value は常にクエリー構文では文字列として扱われます。 value は column の型へと自動的にキャストされます。 キャストにはいくつか制限があります。例えば true や false といった真偽値のリテラルを Bool 型のカラムに使用することができません。 false については空文字列を使う必要がありますが、クエリー構文は column:= 構文をサポートしていません。

キャストについては /reference/cast を参照してください。

  スクリプト構文

スクリプト構文は複雑な検索条件を指定するための構文です。この構文はECMAScriptに似ています。例えば、 _key == "book" は _key の値が "book" のレコードを検索するという意味です。 query_syntax ではすべての値は文字列でしたが、スクリプト構文では値に型があります。例えば、 "book" は文字列で 1 は整数で、 TokenBigram は TokenBigram という名前のオブジェクトです。

スクリプト構文はECMAScriptの構文と完全に互換性があるわけではありません。例えば、 if 制御文や for 繰り返し文や変数定義文といった文をサポートしていません。関数定義もサポートしていません。しかし、独自の演算子を追加しています。独自の演算子はECMAScriptの構文を説明した後に説明します。

  サンプルデータ

使い方を示すために使うスキーマ定義とサンプルデータは以下の通りです。

実行例:

table_create Entries TABLE_PAT_KEY ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Entries content COLUMN_SCALAR Text
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Entries n_likes COLUMN_SCALAR UInt32
# [[0, 1337566253.89858, 0.000355720520019531], true]
table_create Terms TABLE_PAT_KEY|KEY_NORMALIZE ShortText --default_tokenizer TokenBigram
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Terms entries_key_index COLUMN_INDEX|WITH_POSITION Entries _key
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Terms entries_content_index COLUMN_INDEX|WITH_POSITION Entries content
# [[0, 1337566253.89858, 0.000355720520019531], true]
load --table Entries
[
{"_key":    "The first post!",
 "content": "Welcome! This is my first post!",
 "n_likes": 5},
{"_key":    "Groonga",
 "content": "I started to use groonga. It's very fast!",
 "n_likes": 10},
{"_key":    "Mroonga",
 "content": "I also started to use mroonga. It's also very fast! Really fast!",
 "n_likes": 15},
{"_key":    "Good-bye Senna",
 "content": "I migrated all Senna system!",
 "n_likes": 3},
{"_key":    "Good-bye Tritonn",
 "content": "I also migrated all Tritonn system!",
 "n_likes": 3}
]
# [[0, 1337566253.89858, 0.000355720520019531], 5]

ブログエントリ用の Entries テーブルがあります。各エントリはタイトルと内容と「いいね！」数を持っています。タイトルは Entries のキーとします。内容は Entries.content カラムの値とします。「いいね！」数は Entries.n_likes カラムの値とします。

Entries._key カラムと Entries.content カラムには TokenBigram トークナイザーを使ったインデックスを作成します。そのため、 Entries._key と Entries.content は両方とも全文検索できます。

これで例を示すためのスキーマとデータの準備ができました。

  リテラル

  整数

整数リテラルは 1234567890 のような 0 から 9 の並びです。 +29 や -29 のように符号として最初に + または - をつけることができます。整数リテラルは10進数です。8進数や16進数などは使えません。

整数リテラルの最大値は 9223372036854775807 （ = 2 ** 63 - 1 ）です。最小値は -9223372036854775808 （ = -(2 ** 63) ）です。

  浮動小数点数

浮動小数点数リテラルは 3.14 のように、まず 0 から 9 、次に . 、最後に 0 から 9 という並びです。 +3.14 や -3.14 のように符号として最初に + または - をつけることができます。 ${基数}e${指数} や ${基数}E${指数} というフォーマットもサポートしています。例えば、 314e-2 は 3.14 と同じです。

  文字列

文字列リテラルは "..." です。リテラル中の " は \" というように \ を前につけてエスケープします。例えば、 "Say \"Hello!\"." は Say "Hello!". という文字列のリテラルです。

文字列エンコーディングはデータベースのエンコーディングと合わせなければいけません。デフォルトのエンコーディングはUTF-8です。これは configure の --with-default-encoding オプションや /reference/executables/groonga の --encodiong などで変更できます。

  真偽値

真偽値のリテラルは true と false です。 true は真という意味で、 false は偽という意味です。

  NULL

NULLのリテラルは null です。groongaはNULL値をサポートしてませんが、NULLリテラルをサポートしています。

  時間

ノート これはgroonga独自の記法です。

時間のリテラルはありません。文字列での時間記法、整数での時間記法または浮動小数点数での時間記法を使ってください。

文字列での時間記法は "YYYY/MM/DD hh:mm:ss.uuuuuu" または "YYYY-MM-DD hh:mm:ss.uuuuuu" です。 YYYY は西暦、 MM は月、 DD は日、 hh は時、 mm は分、 ss は秒、 uuuuuu はマイクロ秒です。ローカル時間です。例えば、 "2012/07/23 02:41:10.436218" はISO 8601形式では 2012-07-23T02:41:10.436218 になります。

整数での時間記法はUTC時間で1970年1月1日0時0分0秒からの経過秒数を使います。この時間はPOSIX時間とも呼ばれています。例えば、 1343011270 はISO 8601形式では 2012-07-23T02:41:10Z になります。

浮動小数点数での時間記法はUTC時間で1970年1月1日0時0分0秒からの経過秒数と経過マイクロ秒数を使います。例えば、 1343011270.436218 はISO 8601形式では 2012-07-23T02:41:10.346218Z になります。

  座標値

ノート これはgroonga独自の記法です。

座標値のリテラルはありません。文字列での座標値記法を使ってください。

文字列での座標値記法には以下のパターンがあります。

•   "ミリ秒表記の緯度xミリ秒表記の経度"

•   "ミリ秒表記の緯度,ミリ秒表記の経度"

•   "度数表記の緯度x度数表記の経度"

•   "度数表記の緯度,度数表記の経度"

    x と , のどちらも区切り文字として使えます。緯度と経度はミリ秒または度数で指定します。

  配列

配列リテラルは [element1, element2, ...] です。

  オブジェクトリテラル

オブジェクトのリテラルは {name1: value1, name2: value2, ...} です。groongaはまだオブジェクトリテラルをサポートしていません。

  制御構文

スクリプト構文は文をサポートしていません。そのため、 if のような制御文を使うことはできません。制御用の構文は A ? B : C 式だけ使うことができます。

A ? B : C は A が真なら B を返して、そうでなかったら C を返します。

以下は簡単な使用例です。

実行例:

select Entries --filter 'n_likes == (_id == 1 ? 5 : 3)'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         3
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         4,
#         "Good-bye Senna",
#         "I migrated all Senna system!",
#         3
#       ],
#       [
#         5,
#         "Good-bye Tritonn",
#         "I also migrated all Tritonn system!",
#         3
#       ],
#       [
#         1,
#         "The first post!",
#         "Welcome! This is my first post!",
#         5
#       ]
#     ]
#   ]
# ]

この式は _id カラムの値が 1 で n_likes カラムの値が 5 または _id カラムの値が 1 ではなく n_likes カラムの値が 3 のレコードにマッチします。

  グループ化

構文は (...) です。 ... はカンマ区切りの式のリストです。

(...) は1つ以上の式をグループ化します。グループ化された式は1つの式として処理されます。 a && b || c は a と b の両方がマッチするか、 c がマッチすれば式全体がマッチする、という意味になります。 a && (b || c) は a がマッチして b と c はどちらか一方がマッチすれば式全体がマッチする、という意味になります。

以下は簡単な使用例です。

実行例:

select Entries --filter 'n_likes < 5 && content @ "senna" || content @ "fast"'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         3
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         4,
#         "Good-bye Senna",
#         "I migrated all Senna system!",
#         3
#       ],
#       [
#         2,
#         "Groonga",
#         "I started to use groonga. It's very fast!",
#         10
#       ],
#       [
#         3,
#         "Mroonga",
#         "I also started to use mroonga. It's also very fast! Really fast!",
#         15
#       ]
#     ]
#   ]
# ]
select Entries --filter 'n_likes < 5 && (content @ "senna" || content @ "fast")'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         4,
#         "Good-bye Senna",
#         "I migrated all Senna system!",
#         3
#       ]
#     ]
#   ]
# ]

最初の式はグループ化していません。この式は n_likes < 5 と content @ "senna" の両方がマッチするか content @ "fast" がマッチするレコードにマッチします。

2番目の式はグループ化しています。この式は n_likes < 5 にマッチして、 content @ "senna" と content @ "fast" は少なくともどちらか一方にマッチするレコードにマッチします。

  関数呼び出し

構文は name(arugment1, argument2, ...) です。

name(argument1, argument2, ...) は name という関数を引数 argument1, argument2, ... で呼び出します。

利用可能な関数の一覧は /reference/function を参照してください。

以下は簡単な使用例です。

実行例:

select Entries --filter 'edit_distance(_key, "Groonga") <= 1'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         2,
#         "Groonga",
#         "I started to use groonga. It's very fast!",
#         10
#       ],
#       [
#         3,
#         "Mroonga",
#         "I also started to use mroonga. It's also very fast! Really fast!",
#         15
#       ]
#     ]
#   ]
# ]

この式は /reference/functions/edit_distance を使っています。この式は _key カラムの値が "Groonga" に似ているレコードにマッチします。 "Groonga" との類似度は編集距離で計算します。編集距離が1文字以下なら似ているとします。この場合は "Groonga" と "Mroonga" が似ている値です。

  基本的な演算子

groongaはECMAScriptで定義されている演算子をサポートしています。

  算術演算子

以下は算術演算子の説明です。

  加算演算子

構文は number1 + number2 です。

この演算子は number1 と number2 を足した結果を返します。

以下は簡単な使用例です。

実行例:

select Entries --filter 'n_likes == 10 + 5'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         3,
#         "Mroonga",
#         "I also started to use mroonga. It's also very fast! Really fast!",
#         15
#       ]
#     ]
#   ]
# ]

この式は n_likes カラムの値が 15 (= 10 + 5) のレコードにマッチします。

  減算演算子

構文は number1 - number2 です。

この演算子は number2 から number1 を引いた結果を返します。

以下は簡単な使用例です。

実行例:

select Entries --filter 'n_likes == 20 - 5'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         3,
#         "Mroonga",
#         "I also started to use mroonga. It's also very fast! Really fast!",
#         15
#       ]
#     ]
#   ]
# ]

この式は n_likes カラムの値が 15 (= 20 - 5) のレコードにマッチします。

  乗算演算子

構文は number1 * number2 です。

この演算子は number1 と number2 を掛けた結果を返します。

以下は簡単な使用例です。

実行例:

select Entries --filter 'n_likes == 3 * 5'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         3,
#         "Mroonga",
#         "I also started to use mroonga. It's also very fast! Really fast!",
#         15
#       ]
#     ]
#   ]
# ]

この式は n_likes カラムの値が 15 (= 3 * 5) のレコードにマッチします。

  除算演算子

構文は number1 / number2 と number1 % number2 です。

この演算子は number2 を number1 で割ります。 / は商を返します。 % は余りを返します。

以下は簡単な使用例です。

実行例:

select Entries --filter 'n_likes == 26 / 7'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         4,
#         "Good-bye Senna",
#         "I migrated all Senna system!",
#         3
#       ],
#       [
#         5,
#         "Good-bye Tritonn",
#         "I also migrated all Tritonn system!",
#         3
#       ]
#     ]
#   ]
# ]

この式は n_likes カラムの値が 3 (= 26 / 7) のレコードにマッチします。

実行例:

select Entries --filter 'n_likes == 26 % 7'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         1,
#         "The first post!",
#         "Welcome! This is my first post!",
#         5
#       ]
#     ]
#   ]
# ]

この式は n_likes カラムの値が 5 (= 26 % 7) の値にマッチします。

  論理演算子

以下は論理演算子の説明です。

  論理否定演算子

構文は !condition です。

この演算子は condition の真偽値を反転します。

以下は簡単な使用例です。

実行例:

select Entries --filter '!(n_likes == 5)'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         4
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         4,
#         "Good-bye Senna",
#         "I migrated all Senna system!",
#         3
#       ],
#       [
#         5,
#         "Good-bye Tritonn",
#         "I also migrated all Tritonn system!",
#         3
#       ],
#       [
#         2,
#         "Groonga",
#         "I started to use groonga. It's very fast!",
#         10
#       ],
#       [
#         3,
#         "Mroonga",
#         "I also started to use mroonga. It's also very fast! Really fast!",
#         15
#       ]
#     ]
#   ]
# ]

この式は n_likes カラムの値が 5 ではない式にマッチします。

  論理積演算子

構文は condition1 && condition2 です。

この演算子は condition1 と condition2 の両方が真のときに真を返し、そうでなければ偽を返します。

以下は簡単な使用例です。

実行例:

select Entries --filter 'content @ "fast" && n_likes >= 10'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         2,
#         "Groonga",
#         "I started to use groonga. It's very fast!",
#         10
#       ],
#       [
#         3,
#         "Mroonga",
#         "I also started to use mroonga. It's also very fast! Really fast!",
#         15
#       ]
#     ]
#   ]
# ]

この式は content カラムの値が fast を含んでいて、 n_likes カラムの値が 10 以上のレコードにマッチします。

  論理和演算子

構文は condition1 || condition2 です。

この演算子は condition1 と condition2 のどちらか一方が真のときに真を返し、そうでなければ偽を返します。

以下は簡単な使用例です。

実行例:

select Entries --filter 'n_likes == 5 || n_likes == 10'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         1,
#         "The first post!",
#         "Welcome! This is my first post!",
#         5
#       ],
#       [
#         2,
#         "Groonga",
#         "I started to use groonga. It's very fast!",
#         10
#       ]
#     ]
#   ]
# ]

この式は n_likes カラムの値が 5 または 10 のレコードにマッチします。

  論理差演算子

構文は condition1 &! condition2 です。

この演算子は condition1 が真で condition2 が偽のときに真を返し、そうでなければ偽を返します。差集合を返すということです。

以下は簡単な使用例です。

実行例:

select Entries --filter 'content @ "fast" &! content @ "mroonga"'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         2,
#         "Groonga",
#         "I started to use groonga. It's very fast!",
#         10
#       ]
#     ]
#   ]
# ]

この式は content カラムの値が fast を含んでいるが mroonga を含んでいないレコードにマッチします。

  ビット演算子

以下はビット演算子の説明です。

  ビット否定演算子

構文は ~number です。

この演算子は number の各ビットを反転した結果を返します。

以下は簡単な使用例です。

実行例:

select Entries --filter '~n_likes == -6'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         1,
#         "The first post!",
#         "Welcome! This is my first post!",
#         5
#       ]
#     ]
#   ]
# ]

この式は n_likes カラムの値が 5 のレコードにマッチします。なぜならば、 5 の各ビットを反転すると -6 になるからです。

  ビット論理積演算子

構文は number1 & number2 です。

この演算子は number1 と number2 をビット単位で論理積をした結果を返します。

以下は簡単な使用例です。

実行例:

select Entries --filter '(n_likes & 1) == 1'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         4
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         4,
#         "Good-bye Senna",
#         "I migrated all Senna system!",
#         3
#       ],
#       [
#         5,
#         "Good-bye Tritonn",
#         "I also migrated all Tritonn system!",
#         3
#       ],
#       [
#         3,
#         "Mroonga",
#         "I also started to use mroonga. It's also very fast! Really fast!",
#         15
#       ],
#       [
#         1,
#         "The first post!",
#         "Welcome! This is my first post!",
#         5
#       ]
#     ]
#   ]
# ]

この式は n_likes カラムの値が偶数のレコードにマッチします。なぜならば、偶数と 1 のビット単位の論理積は 1 になり、奇数と 1 のビット単位の論理積は 0 になるからです。

  ビット論理和演算子

構文は number1 | number2 です。

この演算子は number1 と number2 をビット単位で論理和した結果を返します。

以下は簡単な使用例です。

実行例:

select Entries --filter 'n_likes == (1 | 4)'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         1,
#         "The first post!",
#         "Welcome! This is my first post!",
#         5
#       ]
#     ]
#   ]
# ]

この式は n_likes カラムの値が 5 (= 1 | 4) のレコードにマッチします。

  ビット排他的論理和演算子

構文は number1 ^ number2 です。

この演算子は number1 と number2 をビット単位で排他的論理和した結果を返します。

以下は簡単な使用例です。

実行例:

select Entries --filter 'n_likes == (10 ^ 15)'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         1,
#         "The first post!",
#         "Welcome! This is my first post!",
#         5
#       ]
#     ]
#   ]
# ]

この式は n_likes カラムの値が 5 (= 10 ^ 15) の値にマッチします。

  シフト演算子

以下はシフト演算子の説明です。

  左シフト演算子

構文は number1 << number2 です。

この演算子は number1 のビットを左に number2 ビットシフトする。

以下は簡単な使用例です。

実行例:

select Entries --filter 'n_likes == (5 << 1)'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         2,
#         "Groonga",
#         "I started to use groonga. It's very fast!",
#         10
#       ]
#     ]
#   ]
# ]

この式は n_likes カラムの値が 10 (= 5 << 1) のレコードにマッチします。

  符号付き右シフト演算子

構文は number1 >> number2 です。

この演算子は number1 のビットを右に number2 ビットシフトします。結果の符号は number1 の符号と同じです。

以下は簡単な使用例です。

実行例:

select Entries --filter 'n_likes == -(-10 >> 1)'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         1,
#         "The first post!",
#         "Welcome! This is my first post!",
#         5
#       ]
#     ]
#   ]
# ]

この式は n_likes カラムの値が 5 (= -(-10 >> 1) = -(-5)) のレコードにマッチします。

  符号なし右シフト演算子

構文は number1 >>> number2 です。

この演算子は number1 のビットを右に number2 ビットシフトします。一番左の number2 ビットには 0 が入ります。

以下は簡単な使用例です。

実行例:

select Entries --filter 'n_likes == (2147483648 - (-10 >>> 1))'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         1,
#         "The first post!",
#         "Welcome! This is my first post!",
#         5
#       ]
#     ]
#   ]
# ]

この式は n_likes カラムの値が 5 (= 2147483648 - (-10 >>> 1) = 2147483648 - 2147483643) のレコードにマッチします。

  比較演算子

以下は比較演算子の説明です。

  等価演算子

構文は object1 == object2 です。

この演算子は object1 が object2 と等しいときは真を返し、そうでなければ偽を返します。

以下は簡単な使用例です。

実行例:

select Entries --filter 'n_likes == 5'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         1,
#         "The first post!",
#         "Welcome! This is my first post!",
#         5
#       ]
#     ]
#   ]
# ]

この式は n_likes カラムの値が 5 の値にマッチします。

  不等価演算子

構文は object1 != object2 です。

この演算子は object1 が object2 と等しくないときに真を返し、そうでなければ偽を返します。

以下は簡単な使用例です。

実行例:

select Entries --filter 'n_likes != 5'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         4
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "_key",
#           "ShortText"
#         ],
#         [
#           "content",
#           "Text"
#         ],
#         [
#           "n_likes",
#           "UInt32"
#         ]
#       ],
#       [
#         4,
#         "Good-bye Senna",
#         "I migrated all Senna system!",
#         3
#       ],
#       [
#         5,
#         "Good-bye Tritonn",
#         "I also migrated all Tritonn system!",
#         3
#       ],
#       [
#         2,
#         "Groonga",
#         "I started to use groonga. It's very fast!",
#         10
#       ],
#       [
#         3,
#         "Mroonga",
#         "I also started to use mroonga. It's also very fast! Really fast!",
#         15
#       ]
#     ]
#   ]
# ]

この式は n_likes カラムの値が 5 ではない式にマッチします。

  小なり演算子

TODO: ...

  以下演算子

TODO: ...

  大なり演算子

TODO: ...

  以上演算子

TODO: ...

  代入演算子

TODO: ...

  独自の演算子

スクリプト構文はECMAScriptの構文に独自の二項演算子を追加しています。これらは検索に特化した操作をします。演算子の最初の文字は @ または * です。

  マッチ演算子

構文は column @ value です。

この演算子は column の転置インデックスを使って value を検索します。普通は全文検索をしますが、タグ検索もできます。これは、タグ検索も転置インデックスを使って実現しているからです。

query_syntax はデフォルトでこの演算子を使っています。

以下は簡単な使用例です。

実行例:

select Entries --filter 'content @ "fast"' --output_columns content
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "content",
#           "Text"
#         ]
#       ],
#       [
#         "I started to use groonga. It's very fast!"
#       ],
#       [
#         "I also started to use mroonga. It's also very fast! Really fast!"
#       ]
#     ]
#   ]
# ]

この式は content カラムの値に fast という単語を含んでいるレコードにマッチします。

  前方一致検索演算子

構文は column @^ value です。

この条件式は value で前方一致検索します。前方一致検索は value で始まる単語を含むレコードを検索します。

カラムの値を高速に前方一致検索できます。ただし、そのカラムにはインデックスを作成し、そのインデックス用のテーブルをパトリシアトライ（ TABLE_PAT_KEY ）またはダブル配列トライ（ TABLE_DAT_KEY ）にしなければいけません。あるいは、パトリシアトライテーブルまたはダブル配列テーブルの _key も高速に前方一致検索できます。 _key にインデックスを作成する必要はありません。

他の種類のテーブルでも前方一致検索を使えますがレコード全件を処理します。レコード数が少ない場合には問題ありませんが、レコード数が多いと時間がかかります。

以下は簡単な使用例です。

実行例:

select Entries --filter '_key @^ "Goo"' --output_columns _key
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ]
#       ],
#       [
#         "Good-bye Tritonn"
#       ],
#       [
#         "Good-bye Senna"
#       ]
#     ]
#   ]
# ]

この式は _key カラムの値が Goo で始まる単語を含むレコードにマッチします。この式には Good-bye Senna と Good-bye Tritonn がマッチします。

  後方一致検索演算子

構文は column @$ value です。

この演算子は value で後方一致検索します。後方一致検索は value で終わる単語を含むレコードを検索します。

カラムの値を高速に後方一致検索できます。ただし、そのカラムにはインデックスを作成し、そのインデックス用のテーブルを KEY_WITH_SIS フラグ付きのパトリシアトライテーブル（ TABLE_PAT_KEY ）にしなければいけません。 KEY_WITH_SIS フラグ付きのパトリシアトライテーブル（ TABLE_PAT_KEY ）の _key 擬似カラムの値も高速に後方一致検索できます。 _key にはインデックスを作成する必要はありません。 _key ベースの高速な後方一致検索よりもカラムベースの高速な後方一致検索を使うことをおすすめします。 _key ベースの高速な後方一致検索は自動的に登録された部分文字列も返ってきます。（TODO: 後方一致検索に関するドキュメントを書いてここからリンクを張る。）

ノート 高速な後方一致検索は日本語のひらがななど非ASCII文字にしか使えません。ASCII文字には高速な後方一致検索を使えません。

後方一致検索は他の種類のテーブルもしくはパトリシアトライを KEY_WITH_SIS フラグなしで使用しているテーブルに対しても使えますが、レコード全件を処理します。レコード数が少ない場合には問題ありませんが、レコード数が多いと時間がかかります。

簡単な例です。ASCII文字ではない文字である日本語のひらがなに対して高速な後方一致検索をしています。

実行例:

table_create Titles TABLE_NO_KEY
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Titles content COLUMN_SCALAR ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
table_create SuffixSearchTerms TABLE_PAT_KEY|KEY_WITH_SIS ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create SuffixSearchTerms index COLUMN_INDEX Titles content
# [[0, 1337566253.89858, 0.000355720520019531], true]
load --table Titles
[
{"content": "ぐるんが"},
{"content": "むるんが"},
{"content": "せな"},
{"content": "とりとん"}
]
# [[0, 1337566253.89858, 0.000355720520019531], 4]
select Titles --query 'content:$んが'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "content",
#           "ShortText"
#         ]
#       ],
#       [
#         2,
#         "むるんが"
#       ],
#       [
#         1,
#         "ぐるんが"
#       ]
#     ]
#   ]
# ]

この式は content カラムの値が んが で終わるレコードにマッチします。この場合は ぐるんが と むるんが にマッチします。

  近傍検索演算子

構文は column *N "word1 word2 ..." です。

この演算子は word1 word2 ... という単語で近傍検索します。近傍検索はすべての単語が含まれていてかつそれぞれの単語が近くにあるレコードを検索します。距離が 10 以内の近さであれば近くにあると判断します。今のところ、この値は変更できません。距離の単位はN-gram系のトークナイザーでは文字数で、形態素解析系のトークナイザーでは単語数です。

（TODO: TokenBigram はASCIIだけの単語はトークンに分割しないという説明を追加すること。このため、 TokenBigram はN-gram系のトークナイザーだけどASCIIだけの単語を扱う時の単位は単語数になる。）

column 用の全文検索用インデックスカラムを定義しておく必要があることに注意してください。

以下は簡単な使用例です。

実行例:

select Entries --filter 'content *N "I fast"'      --output_columns content
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "content",
#           "Text"
#         ]
#       ],
#       [
#         "I started to use groonga. It's very fast!"
#       ]
#     ]
#   ]
# ]
select Entries --filter 'content *N "I Really"'    --output_columns content
# [[0, 1337566253.89858, 0.000355720520019531], [[[0], [["content", "Text"]]]]]
select Entries --filter 'content *N "also Really"' --output_columns content
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "content",
#           "Text"
#         ]
#       ],
#       [
#         "I also started to use mroonga. It's also very fast! Really fast!"
#       ]
#     ]
#   ]
# ]

最初の式は I と fast が含まれていて、かつ、これらの単語が10単語以内近くにあるレコードにマッチします。そのため I also started to use mroonga. It's also very fast! ... にマッチします。 I と fast の間の単語数はちょうど10です。

二番目の式は I と Really が含まれていて、かつ、これらの単語が10単語以内近くにあるレコードにマッチします。そのため、 I also st arted to use mroonga. It's also very fast! Really fast! はマッチしません。 I と Really の間の単語数は11です。

三番目の式は also と Really が含まれていて、かつ、これらの単語が10単語以内近くにあるレコードにマッチします。そのため、 I also started to use mroonga. It's also very fast! Really fast! にマッチします。 also と Really の間の単語数は10です。

  類似文書検索

構文は column *S "document" です。

この演算子は document という文書で類似文書検索します。類似文書検索は document と似た内容を持つレコードを検索します。

column 用の全文検索用インデックスカラムを定義しておく必要があることに注意してください。

以下は簡単な使用例です。

実行例:

select Entries --filter 'content *S "I migrated all Solr system!"' --output_columns content
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "content",
#           "Text"
#         ]
#       ],
#       [
#         "I migrated all Senna system!"
#       ],
#       [
#         "I also migrated all Tritonn system!"
#       ]
#     ]
#   ]
# ]

この式は I migrated all Solr system! と似た内容を持つレコードを検索します。この場合は、 I migrated all XXX system! という内容のレコードがマッチします。

  単語抽出演算子

構文は _key *T "document" です。

この演算子は document から単語を抽出します。単語は _key のテーブルのキーとして登録されていなければいけません。

テーブルはパトリシアトライ（ TABLE_PAT_KEY ）またはダブル配列トライ（ TABLE_DAT_KEY ）でなければいけません。ハッシュテーブル（ TABLE_HASH_KEY ）や配列（ TABLE_NO_KEY ）は最長共通接頭辞検索（Longest Common Prefix Search）できないため使えません。この演算子は最長共通接頭辞検索を使っています。

以下は簡単な使用例です。

実行例:

table_create Words TABLE_PAT_KEY|KEY_NORMALIZE ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
load --table Words
[
{"_key": "groonga"},
{"_key": "mroonga"},
{"_key": "Senna"},
{"_key": "Tritonn"}
]
# [[0, 1337566253.89858, 0.000355720520019531], 4]
select Words --filter '_key *T "Groonga is the successor project to Senna."' --output_columns _key
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_key",
#           "ShortText"
#         ]
#       ],
#       [
#         "groonga"
#       ],
#       [
#         "senna"
#       ]
#     ]
#   ]
# ]

この式は文書 Groonga is the successor project to Senna. に含まれている単語を抽出します。今回は Words に KEY_NORMALIZE フラグが指定されています。そのため、 Words には groonga とロードしていますが Groonga も抽出できています。また、全ての抽出された単語も正規化されています。

  参考

•   /reference/api/grn_expr: grn_expr関連のAPI

  関数

関数はいくつかのコマンドの中で使えます。 commands/select コマンドの --filter 、 --scorer 、 output_columns オプションで使えます。

このセクションでは関数についての説明と組み込みの関数について説明します。

TODO: Add documentations about function.

  edit_distance

  名前

edit_distance - 指定した2つの文字列の編集距離を計算する

  書式

edit_distance(string1, string2)

  説明

groonga組込関数の一つであるedit_distanceについて説明します。組込関数は、script形式のgrn_expr中で呼び出すことができます。

edit_distance() 関数は、string1に指定した文字列とstring2に指定した文字列の間の編集距離を求めます。

  引数

string1 文字列を指定します

string2 もうひとつの文字列を指定します

  返値

指定した2つ文字列の編集距離をUint32型の値として返します。

  例

edit_distance(title, "hoge")
1

  geo_distance

  概要

geo_distance は二点間の距離を計算します。

  構文

geo_distance は二つの点を指定します。引数 approximate_type は省略可能です。

geo_distance(point1, point2)
geo_distance(point1, point2, approximate_type)

approximate_type のデフォルト値は "rectangle" です。 approximate_type を省略した場合、 geo_distance は二点間の距離を "rectangle" が指定されたものとして計算します。

  使い方

geo_distance はgroongaの組み込み関数の一つです。

組み込み関数を /reference/grn_expr にて使うことができます。

geo_distance 関数は point1 と point2 の座標値から二点間の距離(近似値)を計算します。

ノート groongaは三つの組み込み関数を距離の計算のために提供しています。 geo_distance() 、 geo_distance2() 、 geo_distance3() です。これらの違いは距離の計算アルゴリズムにあります。 geo_distance2() と geo_distance3() はバージョン1.2.9より非推奨となりました。 geo_distance2(point1, point2) の代りに geo_distance(point1, point2, "sphere") を使用してください。 geo_distance3(point1, point2) の代りに geo_distance(point1, point2, "ellipsoid") を使用してください。

例とともに geo_distance について学びましょう。このセクションでは簡単な例を示します。

使い方による違いがわかるようにスキーマ定義とサンプルデータを用意しました。これらのサンプルはニューヨークとロンドンを例に距離の計算方法を示します。

1.  距離の計算にlocationカラムの値を使う ( Cities テーブル)

2.  距離の計算に明示的に指定した座標値を使う ( Geo テーブル)

  locationカラムの値を使う

使用例を示すための Cities テーブルのスキーマ定義とサンプルデータは以下の通りです。

table_create Cities TABLE_HASH_KEY ShortText
column_create Cities location COLUMN_SCALAR WGS84GeoPoint
load --table Cities
[
  {
    "_key", "location"
  },
  {
    "New York City", "146566000x-266422000",
  },
]

実行例:

table_create Cities TABLE_HASH_KEY ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Cities location COLUMN_SCALAR WGS84GeoPoint
# [[0, 1337566253.89858, 0.000355720520019531], true]
load --table Cities
[
  {
     "_key", "location"
  },
  {
     "New York City", "146566000x-266422000",
  },
]
# [[0, 1337566253.89858, 0.000355720520019531], 1]

この実行例では location というカラムを持つ Cities テーブルを作成します。 location カラムには座標値を保存します。東京の座標値がサンプルデータとして保存されています。

実行例:

select Cities --output_columns _score --filter 1 --scorer '_score = geo_distance(location, "185428000x-461000", "rectangle")'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_score",
#           "Int32"
#         ]
#       ],
#       [
#         5715104
#       ]
#     ]
#   ]
# ]

このサンプルは geo_distance が location カラムと座標値から距離を計算していることを示します。

geo_distance の第二引数として渡された値 ("185428000x-461000")はロンドンの座標値です。

  明示的に指定した位置を使う

使用例を示すための Geo テーブルのスキーマ定義とサンプルデータは以下の通りです。

table_create Geo TABLE_HASH_KEY ShortText
column_create Geo distance COLUMN_SCALAR Int32
load --table Geo
[
  {
    "_key": "the record for geo_distance() result"
  }
]

実行例:

table_create Geo TABLE_HASH_KEY ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Geo distance COLUMN_SCALAR Int32
# [[0, 1337566253.89858, 0.000355720520019531], true]
load --table Geo
[
  {
    "_key": "the record for geo_distance() result"
  }
]
# [[0, 1337566253.89858, 0.000355720520019531], 1]

この実行例では distance カラムを持つ Geo テーブルを作成します。 distance カラムには距離を保存します。

実行例:

select Geo --output_columns distance --scorer 'distance = geo_distance("146566000x-266422000", "185428000x-461000", "rectangle")'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "distance",
#           "Int32"
#         ]
#       ],
#       [
#         5807750
#       ]
#     ]
#   ]
# ]

このサンプルは geo_distance がロンドンの座標とニューヨークの座標から距離を計算していることを示します。

  引数

  必須引数

必須引数は二つあります。 point1 と point2 です。

  point1

計算しようとしている二点間の開始地点を指定します。

GeoPoint型の値を指定することができます。 [1]

GeoPointについては /reference/types を参照してください。

  point2

計算しようとしている二点間の終了地点を指定します。

GeoPoint型の値か座標を表す文字列を指定することができます。

GeoPointと座標については /reference/types を参照してください。

  省略可能引数

省略可能な引数として approximate_type があります。

  approximate_type

距離を計算するときに地形をどのように近似するかを指定します。

approximate_type の値は以下を指定することができます。

•   rectangle

•   sphere

•   ellipsoid

ノート geo_distance には制限があります。 sphere や ellipsoid を近似方法として選択した場合、子午線や日付変更線、赤道といった境界をまたぐ距離の計算を行うことができません。この制限は rectangle を近似方法として選択した場合にはありません。これはgroongaの実装上の一時的な制限ですが、将来的には修正される予定です。

  rectangle

この引数を指定すると地形を方形近似して距離を計算します。

簡易な式で距離の計算を行うので、高速に距離を求めることができますが、極付近では誤差が増大します。

rect を省略表記として指定することができます。

カラムの値で距離を計算するサンプルは以下の通りです。

実行例:

select Cities --output_columns _score --filter 1 --scorer '_score = geo_distance(location, "185428000x-461000", "rectangle")'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_score",
#           "Int32"
#         ]
#       ],
#       [
#         5715104
#       ]
#     ]
#   ]
# ]

明示的に位置を指定して距離を計算するサンプルは以下の通りです。

実行例:

select Geo --output_columns distance --scorer 'distance = geo_distance("146566000x-266422000", "185428000x-461000", "rectangle")'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "distance",
#           "Int32"
#         ]
#       ],
#       [
#         5807750
#       ]
#     ]
#   ]
# ]

明示的に子午線や赤道、日付変更線をまたぐような位置を指定して距離を計算するサンプルは以下の通りです。

実行例:

select Geo --output_columns distance --scorer 'distance = geo_distance("175904000x8464000", "145508000x-13291000", "rectangle")'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "distance",
#           "Int32"
#         ]
#       ],
#       [
#         1051293
#       ]
#     ]
#   ]
# ]

このサンプルは子午線をまたいだ場合の距離を示します。 geo_distance("175904000x8464000", "145508000x-13291000", "rectangle") はパリ(フランス)からマドリード(スペイン)間の距離を返します。

実行例:

select Geo --output_columns distance --scorer 'distance = geo_distance("146566000x-266422000", "-56880000x-172310000", "rectangle")'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "distance",
#           "Int32"
#         ]
#       ],
#       [
#         6880439
#       ]
#     ]
#   ]
# ]

このサンプルは赤道をまたいだ場合の距離を示します。 geo_distance("146566000x-266422000", "-56880000x-172310000", "rectangle") はニューヨーク(アメリカ)からブラジリア(ブラジル)間の距離を返します。

実行例:

select Geo --output_columns distance --scorer 'distance = geo_distance("143660000x419009000", "135960000x-440760000", "rectangle")'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "distance",
#           "Int32"
#         ]
#       ],
#       [
#         10475205
#       ]
#     ]
#   ]
# ]

このサンプルは日付変更線をまたいだ場合の距離を示します。 geo_distance("143660000x419009000", "135960000x-440760000", "rectangle") は北京(中国)からサンフランシスコ(アメリカ)間の距離を返します。

ノート geo_distance は方形近似をデフォルトとして使用します。 approximate_type を省略すると geo_distance は rectangle が指定されたものとして振舞います。

ノート geo_distance は approximate_type の値が "rectangle" であるときに point1 の値として座標を表す文字列を受けつけます。もし sphere や ellipsoid と一緒に座標を表す文字列を point1 へ指定した場合、 geo_distance は距離の値として0を返します。

  sphere

この引数を指定すると球面近似で地形を近似して距離を計算します。

球面近似は rectangle よりも遅いです。しかし rectangle よりも誤差は小さくなります。

sphr を省略表記として指定することができます。

カラムの値で距離を計算するサンプルは以下の通りです。

実行例:

select Cities --output_columns _score --filter 1 --scorer '_score = geo_distance(location, "185428000x-461000", "sphere")'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_score",
#           "Int32"
#         ]
#       ],
#       [
#         5715102
#       ]
#     ]
#   ]
# ]

  ellipsoid

この引数を指定すると楕円近似で地形を近似して距離を計算します。

ヒュベニの距離計算式により距離を計算します。 sphere よりも遅いですが、 sphere より誤差は小さくなります。

ellip を省略表記として指定することができます。

カラムの値で距離を計算するサンプルは以下の通りです。

実行例:

select Cities --output_columns _score --filter 1 --scorer '_score = geo_distance(location, "185428000x-461000", "ellipsoid")'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_score",
#           "Int32"
#         ]
#       ],
#       [
#         5706263
#       ]
#     ]
#   ]
# ]

  戻り値

geo_distance はFloat型の値を距離として返します。単位はメートルです。 脚注

[1] 日本測地系座標か世界測地系座標のいずれかを指定することができます。

  geo_in_circle

  名前

geo_in_circle - 座標が円の範囲内に存在するかどうかを調べます。

  書式

geo_in_circle(point, center, radious_or_point[, approximate_type])

  説明

groonga組込関数の一つであるgeo_in_circleについて説明します。組込関数は、script形式のgrn_expr中で呼び出すことができます。

geo_in_circle() 関数は、pointに指定した座標が、centerに指定した座標を中心とする円の範囲内にあるかどうかを調べます。

  引数

point 円の範囲内に存在するかどうかを調べる座標を指定します。Point型の値を指定できます。 [1]

center 円の中心となる座標を指定します。Point型の値、あるいは座標を示す文字列を指定できます。

radious_or_point 円の半径を指定します。数値を指定した場合には、半径(単位:メートル)が指定されたものとみなします。 Point型の値、あるいは座標を示す文字列を指定した場合は、円周上の点の一つの座標が指定されたものとみなします。

approximate_type 半径からの距離を求めるために地形をどのように近似するかを指定します。指定できる値は以下の通りです。

"rectangle" 方形近似で近似します。単純な計算式で距離を求めることができるため高速ですが、極付近では誤差が大きくなります。

"rect" と省略して指定することもできます。

この近似方法がデフォルト値です。 approximate_type を省略した場合は方形近似になります。

"sphere" 球面近似で近似します。 "rectangle" よりも遅くなりますが、誤差は小さいです。

"sphr" と省略して指定することもできます。

"ellipsoid" 楕円体近似で近似します。距離の計算にはヒュベニの距離計算式を用います。 "sphere" よりも遅くなりますが、誤差は小さくなります。

"ellip" と省略して指定することもできます。

  返値

pointに指定した座標が円の範囲内にあるかどうかをBool型の値で返します。

  例

geo_in_circle(pos, "100x100", 100)
true
脚注

[1] TokyoGeoPoint(日本測地系座標)かWGS84GeoPoint(世界測地系座標)のいずれかを指定できます。

  geo_in_rectangle

  名前

geo_in_rectangle - 座標が矩形の範囲内に存在するかどうかを調べます。

  書式

geo_in_rectangle(point, top_left, bottom_right)

  説明

groonga組込関数の一つであるgeo_in_rectangleについて説明します。組込関数は、script形式のgrn_expr中で呼び出すことができます。

geo_in_rectangle() 関数は、pointに指定した座標が、top_leftとbottom_rightがなす矩形の範囲内にあるかどうかを調べます。

  引数

point 矩形の範囲内に存在するかどうかを調べる座標を指定します。Point型の値を指定できます。 [1]

top_left 矩形の左上隅となる座標を指定します。Point型の値、あるいは座標を示す文字列を指定できます。

bottom_right 矩形の右下隅となる座標を指定します。Point型の値、あるいは座標を示す文字列を指定できます。

  返値

pointに指定した座標が矩形の範囲内にあるかどうかをBool型の値で返します。

  例

geo_in_rectangle(pos, "150x100", "100x150")
true
脚注

[1] TokyoGeoPoint(日本測地系座標)かWGS84GeoPoint(世界測地系座標)のいずれかを指定できます。

  now

  名前

now - 現在時刻を返す

  書式

now()

  説明

groonga組込関数の一つであるnowについて説明します。組込関数は、script形式のgrn_expr中で呼び出すことができます。

now() 関数は現在時刻に対応するTime型の値を返します。

  返値

現在時刻に対応するTime型のオブジェクトを返します。

  例

now()
1256791194.55541

  query

  概要

query は --match_columns と --query のパラメータを関数の引数として指定することを可能にします。

query はgroongaの組み込み関数の1つで、複数の query 関数を --filter オプションのパラメータとして指定することができます。

そのような柔軟性があるので、 複数の query 関数を組合せることで全文検索の振舞いを制御することができます。

query は /reference/commands/select コマンドの --filter 内でのみ指定できます。

  構文

query は2つの引数が必要です。 match_column と query_string です。

query(match_column, query_string)

  使い方

使い方を示すために使うスキーマ定義とサンプルデータは以下の通りです。

サンプルスキーマ:

実行例:

table_create Documents TABLE_NO_KEY
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Documents content COLUMN_SCALAR Text
# [[0, 1337566253.89858, 0.000355720520019531], true]
table_create Terms TABLE_PAT_KEY|KEY_NORMALIZE ShortText --default_tokenizer TokenBigram
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Terms documents_content_index COLUMN_INDEX|WITH_POSITION Documents content
# [[0, 1337566253.89858, 0.000355720520019531], true]
table_create Users TABLE_NO_KEY
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Users name COLUMN_SCALAR ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Users memo COLUMN_SCALAR ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
table_create Lexicon TABLE_HASH_KEY ShortText \
  --default_tokenizer TokenBigramSplitSymbolAlphaDigit \
  --normalizer NormalizerAuto
column_create Lexicon users_name COLUMN_INDEX|WITH_POSITION Users name
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Lexicon users_memo COLUMN_INDEX|WITH_POSITION Users memo
# [[0, 1337566253.89858, 0.000355720520019531], true]

サンプルデータ:

実行例:

load --table Users
[
{"name": "Alice", "memo": "groonga user"},
{"name": "Alisa", "memo": "mroonga user"},
{"name": "Bob",   "memo": "rroonga user"},
{"name": "Tom",   "memo": "nroonga user"},
{"name": "Tobby", "memo": "groonga and mroonga user. mroonga is ..."},
]
# [[0, 1337566253.89858, 0.000355720520019531], true]
# [[0, 1337566253.89858, 0.000355720520019531], 5]

--match_columns と --query 引数を使わずにキーワード'alice'を``query`` 関数を使って検索する簡単な使用例です。

実行例:

select Users --output_columns name,_score --filter 'query("name * 10", "alice")'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "name",
#           "ShortText"
#         ],
#         [
#           "_score",
#           "Int32"
#         ]
#       ],
#       [
#         "Alice",
#         10
#       ]
#     ]
#   ]
# ]

上記のクエリを実行する際、'alice'というキーワードには重みづけとして値10を設定します。

query あり/なしで対照的な例がこちらです。

実行例:

select Users --output_columns name,memo,_score --match_columns "memo * 10" --query "memo:@groonga OR memo:@mroonga OR memo:@user" --sortby -_score
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         5
#       ],
#       [
#         [
#           "name",
#           "ShortText"
#         ],
#         [
#           "memo",
#           "ShortText"
#         ],
#         [
#           "_score",
#           "Int32"
#         ]
#       ],
#       [
#         "Tobby",
#         "groonga and mroonga user. mroonga is ...",
#         4
#       ],
#       [
#         "Alice",
#         "groonga user",
#         2
#       ],
#       [
#         "Alisa",
#         "mroonga user",
#         2
#       ],
#       [
#         "Bob",
#         "rroonga user",
#         1
#       ],
#       [
#         "Tom",
#         "nroonga user",
#         1
#       ]
#     ]
#   ]
# ]

この場合、'groonga'と'mroonga'と'user'というキーワードは同じ重みづけがされています。この方法ではキーワードごとに異なる重みづけを行うことはできません。

実行例:

select Users --output_columns name,memo,_score --filter 'query("memo * 10", "groonga") || query("memo * 20", "mroonga") || query("memo * 1", "user")' --sortby -_score
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         5
#       ],
#       [
#         [
#           "name",
#           "ShortText"
#         ],
#         [
#           "memo",
#           "ShortText"
#         ],
#         [
#           "_score",
#           "Int32"
#         ]
#       ],
#       [
#         "Tobby",
#         "groonga and mroonga user. mroonga is ...",
#         51
#       ],
#       [
#         "Alisa",
#         "mroonga user",
#         21
#       ],
#       [
#         "Alice",
#         "groonga user",
#         11
#       ],
#       [
#         "Tom",
#         "nroonga user",
#         1
#       ],
#       [
#         "Bob",
#         "rroonga user",
#         1
#       ]
#     ]
#   ]
# ]

一方、複数の query を指定することで、'groonga'と'mroonga'と'user'それぞれのキーワードに対し異なる重みづけを行えます。

結果として、意図した様に異なる重みづけを行いつつ全文検索の振舞いを制御することができます。

  引数

必須引数は二つあります。 match_column と query_string です。

  match_column
match_columns と同様のパラメータを指定します。

match_columnについては select-match-columns を参照してください。

  query_string
query と同様のパラメータを指定します。

query stringについては select-query を参照してください。

  戻り値

query は真偽値(trueもしくはfalse)を返します。

  TODO

•   query_expansionのサポート

•   query_flagsのサポート

  参考

•   /reference/commands/select

  rand

  名前

rand - 乱数を生成する

  書式

rand([max])

  説明

groonga組込関数の一つであるrandについて説明します。組込関数は、script形式のgrn_expr中で呼び出すことができます。

rand() 関数は 0 から max の間の疑似乱数整数を返します。

  引数

max 返値の最大値を指定します。省略した場合は RAND_MAX が指定されたものとみなされます。

  返値

0 と max の間の数を表すInt32型の値を返します。

  例

rand(10)
3

  snippet_html

ご用心 この機能は実験的です。APIが変わる可能性があります。

  概要

snippet_html は対象テキスト中から検索キーワード周辺のテキスト（ KWIC 。 KeyWord In Context ）を抽出します。抽出されたテキストのことをスニペットと呼びます。スニペットはHTML中に埋め込みやすいように処理されています。 < や > などの特殊文字は &lt; や &gt; にエスケープされています。キーワードは <span class="keyword"> と </span> で囲まれています。たとえば、 I am a groonga user. <3 という対象テキストのキーワード groonga でのスニペットは I am a <span class="keyword">groonga</span> user. &lt;3 となります。

  構文

snippet_html の引数は1つだけです:

snippet_html(column)

snippet_html は内部にはたくさんのオプションがありますが、今はまだ指定できません。じきに指定できるようになる予定です。

  使い方

使い方を示すために使うスキーマ定義とサンプルデータは以下の通りです。

実行例:

table_create Documents TABLE_NO_KEY
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Documents content COLUMN_SCALAR Text
# [[0, 1337566253.89858, 0.000355720520019531], true]
table_create Terms TABLE_PAT_KEY|KEY_NORMALIZE ShortText --default_tokenizer TokenBigram
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Terms documents_content_index COLUMN_INDEX|WITH_POSITION Documents content
# [[0, 1337566253.89858, 0.000355720520019531], true]
load --table Documents
[
["content"],
["Groonga is a fast and accurate full text search engine based on inverted index. One of the characteristics of groonga is that a newly registered document instantly appears in search results. Also, groonga allows updates without read locks. These characteristics result in superior performance on real-time applications."],
["Groonga is also a column-oriented database management system (DBMS). Compared with well-known row-oriented systems, such as MySQL and PostgreSQL, column-oriented systems are more suited for aggregate queries. Due to this advantage, groonga can cover weakness of row-oriented systems."]
]
# [[0, 1337566253.89858, 0.000355720520019531], 2]

snippet_html は /reference/commands/select コマンドの --output_columns 内でのみ指定できます。

groonga 2.0.9では output_columns 内での関数呼び出しはまだ実験的な機能なので、明示的に --command_version 2 オプションを指定する必要があります。この機能はじきに有効になる予定です。

また、 --query と --filter オプションも指定する必要があります。（どちらか一方でも構いません。）これは、 --query と --filter オプションからキーワードを抽出しているためです。

以下の例は --query "fast performance" を使っています。この場合は、キーワードとして fast と performance を使います。

実行例:

select Documents --output_columns "snippet_html(content)" --command_version 2 --match_columns content --query "fast performance"
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "snippet_html",
#           "null"
#         ]
#       ],
#       [
#         [
#           "Groonga is a <span class=\"keyword\">fast</span> and accurate full text search engine based on inverted index. One of the characteristics of groonga is that a newly registered document instantly appears in search results. Also, gro",
#           "onga allows updates without read locks. These characteristics result in superior <span class=\"keyword\">performance</span> on real-time applications."
#         ]
#       ]
#     ]
#   ]
# ]

--query "fast performance" は最初のレコードの内容にだけマッチします。 snippet_html(content) は、テキスト中からキーワード fast と performance の少なくともどちらか一方を含んでいるテキストの断片を抽出します。今回は2箇所抽出しています。そして、抽出したテキストの断片内にあるキーワードを <span class="keyword"> と </span> で囲みます。

テキストの断片数は多くても3です。4つ以上のテキストの断片が抽出できるときは、最初の3つだけを使います。

テキストの断片の最大サイズは200バイトです。単位は文字数ではなくバイトです。挿入される <span keyword="keyword"> と </span> のバイト数はこのサイズの中には含まれません。

テキストの断片の最大数とテキストの断片の最大サイズはカスタマイズできません。

カラムの代わりに文字列リテラルを指定することもできます。

実行例:

select Documents --output_columns 'snippet_html("Groonga is very fast fulltext search engine.")' --command_version 2 --match_columns content --query "fast performance"
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "snippet_html",
#           "null"
#         ]
#       ],
#       [
#         [
#           "Groonga is very <span class=\"keyword\">fast</span> fulltext search engine."
#         ]
#       ]
#     ]
#   ]
# ]

  戻り値

snippet_html は文字列の配列を返します。それぞれの要素がスニペットになります:

[SNIPPET1, SNIPPET2, SNIPPET3]

スニペットには1つ以上のキーワードが含まれています。 <span keyword="keyword"> と </span> を除いたスニペットの最大サイズは200byteです。単位は文字数ではなくてバイトです。

配列のサイズは0以上3以下です。最大サイズの3は、じきにカスタマイズできるようになる予定です。

  TODO

•   テキストの断片の最大数をカスタマイズできるようにする。

•   テキストの断片最大サイズをカスタマイズできるようにする。

•   キーワードをカスタマイズできるようにする。

•   キーワードを囲むタグをカスタマイズできるようにする。

•   正規化の方法をカスタマイズできるようにする。

•   オブジェクトリテラル形式でのオプション指定をサポートする。

  参考

•   /reference/commands/select

  インデックス構築

groongaは2.0.0から動的なインデックス構築方法と静的なインデックス構築方法を両方サポートしています。

  動的なインデックス構築方法

動的なインデックス構築方法では、登録された文書はインデックス構築中にすぐに検索できるようになります。しかし、静的なインデックス構築方法に比べてコストがかかります。

動的なインデックス構築方法は鮮度が重要な検索システムに適しています。例えば、つぶやきやニュースやブログ記事などを検索するシステムは鮮度が重要になるでしょう。動的なインデックス構築方法はできたばかりの文書を検索できるようにし、インデックス構築中も検索できます。

  静的なインデックス構築方法

静的なインデックス構築方法では、動的なインデックス構築方法よりもインデックス構築にかかるコストが小さくなります。インデックス構築時間は短くなるでしょう。インデックスは小さくなるでしょう。インデックス構築に必要なリソースは少なくなるでしょう。しかし、登録中の文書は登録しようとしている全ての文書のインデックス構築が終わるまで検索できません。

静的なインデックス構築方法は消費リソースが少ないことが重要な検索システムに適しています。鮮度が重要でないシステムであれば静的なインデックス構築方法が適しているでしょう。例えば、リファレンスマニュアルを検索するシステムは鮮度を重視しません。これは、リファレンスマニュアルはリリース時にだけ更新されるだけだからです。

  使い方

groongaはデフォルトで動的なインデックス構築方法を使います。文書を登録するとすぐに検索できるようになります。

すでにデータが格納されているカラムにインデックスを追加した場合は静的なインデックス構築方法を使います。

スキーマを定義します。

実行例:

table_create Tweets TABLE_NO_KEY
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Tweets content COLUMN_SCALAR ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
table_create Lexicon TABLE_HASH_KEY|KEY_NORMALIZE ShortText --default_tokenizer TokenBigram
# [[0, 1337566253.89858, 0.000355720520019531], true]

データを登録します:

実行例:

load --table Tweets
[
{"content":"Hello!"},
{"content":"I just start it!"},
{"content":"I'm sleepy... Have a nice day... Good night..."}
]
# [[0, 1337566253.89858, 0.000355720520019531], 3]

インデックスなしで検索します。これは何もヒットしません:

実行例:

select Tweets --match_columns content --query 'good nice'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         0
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "content",
#           "ShortText"
#         ]
#       ]
#     ]
#   ]
# ]

Tweets.content 用のインデックスを作成します。すでに Tweets.content に登録されているデータは静的なインデックス構築方法でインデックスを構築します:

実行例:

column_create Lexicon tweet COLUMN_INDEX|WITH_POSITION Tweets content
# [[0, 1337566253.89858, 0.000355720520019531], true]

インデックスありで検索します。1件ヒットします:

実行例:

select Tweets --match_columns content --query 'good nice'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         1
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "content",
#           "ShortText"
#         ]
#       ],
#       [
#         3,
#         "I'm sleepy... Have a nice day... Good night..."
#       ]
#     ]
#   ]
# ]

もう一度データを登録します。このデータ用のインデックスは動的なインデックス構築方法で構築します。

実行例:

load --table Tweets
[
{"content":"Good morning! Nice day."},
{"content":"Let's go shopping."}
]
# [[0, 1337566253.89858, 0.000355720520019531], 2]

検索すると新しく登録されたレコードもヒットします:

実行例:

select Tweets --match_columns content --query 'good nice'
# [
#   [
#     0,
#     1337566253.89858,
#     0.000355720520019531
#   ],
#   [
#     [
#       [
#         2
#       ],
#       [
#         [
#           "_id",
#           "UInt32"
#         ],
#         [
#           "content",
#           "ShortText"
#         ]
#       ],
#       [
#         3,
#         "I'm sleepy... Have a nice day... Good night..."
#       ],
#       [
#         4,
#         "Good morning! Nice day."
#       ]
#     ]
#   ]
# ]

  Log

Groonga has two log files. They are process log and query log. Process log is for all of executables/groonga works. Query log is just for query processing.

  Process log

Process log is enabled by default. Log path can be customized by --log-path option. Each log has its log level. If a log is smaller than groonga process' log level, it's not logged. Log level can be customized by -l or commands/log_level.

  フォーマット

Process log uses the following format:

#{TIME_STAMP}|#{L}| #{MESSAGE}

TIME_STAMP
    It's time stamp uses the following format:

    YYYY-MM-DD hh:mm:ss.SSSSSS

YYYY
    Year with four digits.

MM  Month with two digits.

DD  Day with two digits.

hh  Hour with two digits.

mm  Minute with two digits.

ss  Second with two digits.

SSSSSS
    Microsecond with six digits.

    実行例:

    2011-07-05 06:25:18.345734

L   Log level with a character. Here is a character and log level map.

E   Emergency

A   Alert

C   Critical

e   Error

w   Warning

n   Notification

i   Information

d   Debug

-   Dump

    実行例:

    E

MESSAGE
    Details about the log with free format.

    実行例:

    log opened.

    実行例:

    2011-07-05 08:35:09.276421|n| grn_init
    2011-07-05 08:35:09.276553|n| RLIMIT_NOFILE(4096,4096)

  Query log

Query log is disabled by default. It can be enabled by --query-log-path option.

  フォーマット

Query log uses the following formats:

#{TIME_STAMP}|#{MESSAGE}
#{TIME_STAMP}|#{ID}|>#{QUERY}
#{TIME_STAMP}|#{ID}|:#{ELAPSED_TIME} #{PROGRESS}
#{TIME_STAMP}|#{ID}|<#{ELAPSED_TIME} #{RETURN_CODE}

TIME_STAMP
    It's time stamp uses the following format:

    YYYY-MM-DD hh:mm:ss.SSSSSS

YYYY
    Year with four digits.

MM  Month with two digits.

DD  Day with two digits.

hh  Hour with two digits.

mm  Minute with two digits.

ss  Second with two digits.

SSSSSS
    Microsecond with six digits.

    実行例:

    2011-07-05 06:25:18.345734

ID  ID of a thread. Groonga process creates threads to process requests concurrently. Each thread outputs some logs for a request. This ID can be used to extract a log sequence by a thread.

    実行例:

    45ea3034

>   A character that indicates query is started.

:   A character that indicates query is processing.

<   A character that indicates query is finished.

MESSAGE
    Details about the log with free format.

    実行例:

    query log opened.

QUERY
    A query to be processed.

    実行例:

    select users --match_columns hobby --query music

ELAPSED_TIME
    Elapsed time in nanoseconds since query is started.

    実行例:

    000000000075770
    (It means 75,770 nanoseconds.)

PROGRESS
    A processed work at the time.

    実行例:

    select(313401)
    (It means that 'select' is processed and 313,401 records are remained.)

RETURN_CODE
    A return code for the query.

    実行例:

    rc=0
    (It means return code is 0. 0 means GRN_SUCCESS.)

    実行例:

    2011-07-05 06:25:19.458756|45ea3034|>select Properties --limit 0
    2011-07-05 06:25:19.458829|45ea3034|:000000000072779 select(19)
    2011-07-05 06:25:19.458856|45ea3034|:000000000099998 output(0)
    2011-07-05 06:25:19.458875|45ea3034|<000000000119062 rc=0
    2011-07-05 06:25:19.458986|45ea3034|>quit

  API

TODO...

仕様

  GQTP

GQTPはGroonga Query Transfer Protocolの頭文字です。GQTPはgroonga用の独自プロトコルです。

  プロトコル

GQTPはステートフルなクライアント・サーバーモデルのプロトコルです。以下の流れが1つの処理単位です:

•   クライアントがリクエストを送る

•   サーバーがリクエストを受け取る

•   サーバーがリクエストを処理する

•   サーバーがレスポンスを返す

•   クライアントがレスポンスを受け取る

    1つのセッション内で0個以上の処理単位を実行できます。

    リクエストもレスポンスもGQTPヘッダーとボディから成ります。GQTPヘッダーは固定長のデータです。ボディは可変長サイズのデータです。ボディのサイズはGQTPヘッダーの中に入っています。GQTPではボディの中身については何も定義しません。

  GQTPヘッダー

GQTPヘッダーは以下の符号なし整数値から成ります:
名前 | サイズ | 説明
protocol | 1byte | プロトコルの種類。
query_type | 1byte | ボディのコンテントタイプ。
key_length | 2byte | 未使用。
level | 1byte | 未使用。
flags | 1byte | フラグ。
status | 2byte | リターンコード。
size | 4byte | ボディのサイズ。
opaque | 4byte | 未使用。
cas | 8byte | 未使用。

ヘッダーのすべての値はネットワークバイトオーダーを使っています。

以下のセクションではそれぞれのヘッダーの値で利用可能な値について説明します。

GQTPヘッダーは全部で24byteになります。

  protocol

リクエストのGQTPヘッダーでもレスポンスのGQTPヘッダーでも、この値は常に 0xc7 になります。

  query_type

この値は以下のいずれかの値です:
名前 | 値 | 説明
NONE | 0 | 自由形式。
TSV | 1 | 値をタブで区切った形式。
JSON | 2 | JSON。
XML | 3 | XML。
MSGPACK | 4 | MessagePack。

リクエストGQTPヘッダーでは使われません。

レスポンスGQTPヘッダーで使われます。ボディは指定した形式にします。

  flags

この値は以下の値をビット単位ORしたものになります:
名前 | 値 | 説明
MORE | 0x01 | まだデータがあります。
TAIL | 0x02 | これ以上データはありません。
HEAD | 0x04 | 未使用。
QUIET | 0x08 | レスポンスを出力しません。
QUIT | 0x10 | 終了します。

MORE あるいは TAIL フラグは必ず指定しないといけません。

MORE フラグを使うときは QUIET フラグも使うべきです。リクエストが途中のときはレスポンスを出力する必要がないからです。

セッションを終了するときは QUIT フラグを使ってください。

  status

利用可能な値です。将来的に新しいステータスが追加される可能性があります。

•   0: SUCCESS

•   1: END_OF_DATA

•   65535: UNKNOWN_ERROR

•   65534: OPERATION_NOT_PERMITTED

•   65533: NO_SUCH_FILE_OR_DIRECTORY

•   65532: NO_SUCH_PROCESS

•   65531: INTERRUPTED_FUNCTION_CALL

•   65530: INPUT_OUTPUT_ERROR

•   65529: NO_SUCH_DEVICE_OR_ADDRESS

•   65528: ARG_LIST_TOO_LONG

•   65527: EXEC_FORMAT_ERROR

•   65526: BAD_FILE_DESCRIPTOR

•   65525: NO_CHILD_PROCESSES

•   65524: RESOURCE_TEMPORARILY_UNAVAILABLE

•   65523: NOT_ENOUGH_SPACE

•   65522: PERMISSION_DENIED

•   65521: BAD_ADDRESS

•   65520: RESOURCE_BUSY

•   65519: FILE_EXISTS

•   65518: IMPROPER_LINK

•   65517: NO_SUCH_DEVICE

•   65516: NOT_A_DIRECTORY

•   65515: IS_A_DIRECTORY

•   65514: INVALID_ARGUMENT

•   65513: TOO_MANY_OPEN_FILES_IN_SYSTEM

•   65512: TOO_MANY_OPEN_FILES

•   65511: INAPPROPRIATE_I_O_CONTROL_OPERATION

•   65510: FILE_TOO_LARGE

•   65509: NO_SPACE_LEFT_ON_DEVICE

•   65508: INVALID_SEEK

•   65507: READ_ONLY_FILE_SYSTEM

•   65506: TOO_MANY_LINKS

•   65505: BROKEN_PIPE

•   65504: DOMAIN_ERROR

•   65503: RESULT_TOO_LARGE

•   65502: RESOURCE_DEADLOCK_AVOIDED

•   65501: NO_MEMORY_AVAILABLE

•   65500: FILENAME_TOO_LONG

•   65499: NO_LOCKS_AVAILABLE

•   65498: FUNCTION_NOT_IMPLEMENTED

•   65497: DIRECTORY_NOT_EMPTY

•   65496: ILLEGAL_BYTE_SEQUENCE

•   65495: SOCKET_NOT_INITIALIZED

•   65494: OPERATION_WOULD_BLOCK

•   65493: ADDRESS_IS_NOT_AVAILABLE

•   65492: NETWORK_IS_DOWN

•   65491: NO_BUFFER

•   65490: SOCKET_IS_ALREADY_CONNECTED

•   65489: SOCKET_IS_NOT_CONNECTED

•   65488: SOCKET_IS_ALREADY_SHUTDOWNED

•   65487: OPERATION_TIMEOUT

•   65486: CONNECTION_REFUSED

•   65485: RANGE_ERROR

•   65484: TOKENIZER_ERROR

•   65483: FILE_CORRUPT

•   65482: INVALID_FORMAT

•   65481: OBJECT_CORRUPT

•   65480: TOO_MANY_SYMBOLIC_LINKS

•   65479: NOT_SOCKET

•   65478: OPERATION_NOT_SUPPORTED

•   65477: ADDRESS_IS_IN_USE

•   65476: ZLIB_ERROR

•   65475: LZO_ERROR

•   65474: STACK_OVER_FLOW

•   65473: SYNTAX_ERROR

•   65472: RETRY_MAX

•   65471: INCOMPATIBLE_FILE_FORMAT

•   65470: UPDATE_NOT_ALLOWED

•   65469: TOO_SMALL_OFFSET

•   65468: TOO_LARGE_OFFSET

•   65467: TOO_SMALL_LIMIT

•   65466: CAS_ERROR

•   65465: UNSUPPORTED_COMMAND_VERSION

  size

ボディのサイズです。ボディの最大サイズは4GiBです。これは size が4byteの符号なし整数だからです。4GiB以上のサイズのデータを送りたい場合は MORE フラグを使ってください。

  例

TODO

  参照

TODO

  検索

/reference/commands/select コマンドがqueryパラメータを使ってどのように検索するのかを説明します。

  検索の挙動

検索の挙動には以下の3種類あり、検索結果によって動的に使い分けています。

1.  完全一致検索

2.  非わかち書き検索

3.  部分一致検索

    どのように検索の挙動を使い分けているかを説明する前に、まず、それぞれの検索の挙動を説明します。

  完全一致検索

検索対象文書は複数の語彙にトークナイズ(分割)され、それぞれを単位とした語彙表に索引を管理します。 検索キーワードも同一の方法でトークナイズされます。

このとき、検索キーワードをトークナイズした結果得られる語彙の配列と同一の配列を含む文書を検索する処理を完全一致検索と呼んでいます。

たとえば、TokenMecabトークナイザを使用した索引では「東京都民」という文字列は 東京 / 都民

という二つの語彙の配列として格納されます。この索引に対して「東京都」というキーワードで検索した時、このキーワードは、 東京 / 都

という二つの語彙の配列として処理されます。この語彙の並びは、「東京 / 都民」という語彙の並びには一致しませんので、完全一致検索ではヒットしません。

これに対して、TokenBigramトークナイザを使用した索引では「東京都民」という文字列は 東京 / 京都 / 都民 / 民

という四つの語彙の配列として格納されます。この索引に対して「東京都」というキーワードで検索した時、このキーワードは、 東京 / 京都

という二つの語彙の配列として処理されます。この語彙の並びは、「東京 / 京都 / 都民」という語彙の並びに含まれますので、完全一致検索でヒットします。

なお、TokenBigramトークナイザでは、アルファベット・数値・記号文字列についてはbigramを生成せず、一つの連続したトークンとして扱います。たとえば、「楽しいbilliard」という文字列は、 楽し / しい / billiard

という三つの語彙の配列として格納されます。これに対して「bill」というキーワードで検索した時、このキーワードは、 bill

という一つの語彙として処理されます。この語彙の並びは「楽し / しい / billiard」という語彙の並びには含まれないので、完全一致でヒットしません。

これに対して、TokenBigramSplitSymbolAlphaトークナイザではアルファベット文字列についてもbigramを生成し、「楽しいbilliard」という文字列は、 楽し / しい / いb / bi / il / ll / li / ia / ar / rd / d

という十一の語彙の配列として格納されます。これに対して「bill」というキーワードで検索した時、このキーワードは、 bi / il / ll

という三つの語彙として処理されます。この語彙の並びは「楽し / しい / いb / bi / il / ll / li / ia / ar / rd / d」という語彙の並びに含まれるので、完全一致でヒットします。

  非わかち書き検索

非わかち書き検索はパトリシア木で語彙表を構築している場合のみ利用可能です。

非わかち書き検索の挙動はTokenBigramなどN-gram系のトークナイザーを利用している場合とTokenMecabトークナイザーを利用している場合で挙動が変わります。

N-gram系のトークナイザーを利用している場合はキーワードで前方一致検索をします。

例えば、「bill」というキーワードで検索した場合、「bill」も「billiard」もヒットします。

TokenMeCabトークナイザーの場合はわかち書き前のキーワードで前方一致検索をします。

例えば、「スープカレー」というキーワードで検索した場合、「スープカレーバー」（1単語扱い）にヒットしますが、「スープカレー」（"スープ"と"カレー"の2単語扱い）や「スープカレーライス」（"スープ"と"カレーライス"の2単語扱い）にはヒットしません。

  部分一致検索

部分一致検索はパトリシア木で語彙表を構築していて、かつ、KEY_WITH_SISオプションを指定している場合のみ利用可能です。KEY_WITH_SISオプションが指定されていない場合は非わかち書き検索と同等です。

部分一致検索の挙動はTokenBigramなどN-gram系のトークナイザーを利用している場合とTokenMecabトークナイザーを利用している場合で挙動が変わります。

Bigramの場合は前方一致検索と中間一致検索と後方一致検索を行います。

例えば、「ill」というキーワードで検索した場合、「bill」も「billiard」もヒットします。

TokenMeCabトークナイザーの場合はわかち書き後のキーワードで前方一致検索と中間一致検索と後方一致検索をします。

例えば、「スープカレー」というキーワードで検索した場合、「スープカレー」（"スープ"と"カレー"の2単語扱い）や「スープカレーライス」（"スープ"と"カレーライス"の2単語扱い）、「スープカレーバー」（1単語扱い）にもヒットします。

  検索の使い分け

groongaは基本的に完全一致検索のみを行います。完全一致検索でのヒット件数が所定の閾値以下の場合に限り、非わかち書き検索を行い、それでもヒット件数が閾値以下の場合は部分一致検索を行います。（閾値のデフォルト値は0です。）

ただし、すでに検索結果セットが存在する場合はたとえヒット件数が閾値以下でも完全一致検索のみを行います。

例えば、以下のようなクエリの場合は、それぞれの検索でヒット件数が閾値以下の場合は完全一致検索、非わかち書き検索、部分一致検索を順に行います。:

select Shops --match_column description --query スープカレー

しかし、以下のように全文検索を行う前に検索結果セットが存在する場合は完全一致検索のみを行います。（point > 3で閾値の件数よりヒットしている場合）:

select Shops --filter '"point > 3 && description @ \"スープカレー\""'

そのため、descriptionに「スープカレーライス」が含まれていても、「スープカレーライス」は「スープカレー」に完全一致しないのでヒットしません。

制限事項

groongaにはいくつか制限事項があります。

  テーブルの制限

テーブルには以下の制限があります。

•   1つのキーの最大サイズ: 4096Bytes

•   キーのサイズを合計した上限値: 4GByte

    実際には他の諸条件の制約により上記の値まで到達しない場合もあります。

  インデックス上限値

1つのインデックスにおける論理上の上限値は以下のとおりです。

•   最大レコード数: 268,435,455 (約2億6千万)

•   最大語彙数: 268,435,455 (約2億6千万)

•   最大インデックスサイズ: 256GByte

    実際には他の諸条件の制約により上記の値まで到達しない場合もあります。

トラブルシューティング

  同じ検索キーワードなのに全文検索結果が異なる

同じ検索キーワードでも一緒に指定するクエリによっては全文検索の結果が異なることがあります。ここでは、その原因と対策方法を説明します。

  例

まず、実際に検索結果が異なる例を説明します。

DDLは以下の通りです。BlogsテーブルのbodyカラムをTokenMecabトークナイザーを使ってトークナイズしてからインデックスを作成しています。:

table_create Blogs TABLE_NO_KEY
column_create Blogs body COLUMN_SCALAR ShortText
column_create Blogs updated_at COLUMN_SCALAR Time
table_create Terms TABLE_PAT_KEY|KEY_NORMALIZE ShortText --default_tokenizer TokenMecab
column_create Terms blog_body COLUMN_INDEX|WITH_POSITION Blogs body

テスト用のデータは1件だけ投入します。:

load --table Blogs
[
  ["body", "updated_at"],
  ["東京都民に深刻なダメージを与えました。", "2010/9/21 10:18:34"],
]

まず、全文検索のみで検索します。この場合ヒットします。:

> select Blogs --filter 'body @ "東京都"'
[[0,4102.268052438,0.000743783],[[[1],[["_id","UInt32"],["updated_at","Time"],["body","ShortText"]],[1,1285031914.0,"東京都民に深刻なダメージを与えました。"]]]]

続いて、範囲指定と全文検索を組み合わせて検索します（1285858800は2010/10/1 0:0:0の秒表記）。この場合もヒットします。:

> select Blogs --filter 'body @ "東京都" && updated_at < 1285858800'
[[0,4387.524084839,0.001525487],[[[1],[["_id","UInt32"],["updated_at","Time"],["body","ShortText"]],[1,1285031914.0,"東京都民に深刻なダメージを与えました。"]]]]

最後に、範囲指定と全文検索の順番を入れ替えて検索します。個々の条件は同じですが、この場合はヒットしません。:

> select Blogs --filter 'updated_at < 1285858800 && body @ "東京都"'
[[0,4400.292570838,0.000647716],[[[0],[["_id","UInt32"],["updated_at","Time"],["body","ShortText"]]]]]

どうしてこのような挙動になるかを説明します。

  原因

このような挙動になるのは全文検索時に複数の検索の挙動を使い分けているからです。ここでは簡単に説明するので、詳細は /spec/search を参照してください。

検索の挙動には以下の3種類があります。

1.  完全一致検索

2.  非わかち書き検索

3.  部分一致検索

    groongaは基本的に完全一致検索のみを行います。上記の例では「東京都民に深刻なダメージを与えました。」を「東京都」というクエリで検索していますが、TokenMecabトークナイザーを使っている場合はこのクエリはマッチしません。

    検索対象の「東京都民に深刻なダメージを与えました。」は 東京 / 都民 / に / 深刻 / な / ダメージ / を / 与え / まし / た / 。

    とトークナイズされますが、クエリの「東京都」は 東京 / 都

    とトークナイズされるため、完全一致しません。

    groongaは完全一致検索した結果のヒット件数が所定の閾値を超えない場合に限り、非わかち書き検索を行い、それでもヒット件数が閾値を超えない場合は部分一致検索を行います（閾値は1がデフォルト値となっています）。このケースのデータは部分一致検索ではヒットするので、「東京都」クエリのみを指定するとヒットします。

    しかし、以下のように全文検索前にすでに閾値が越えている場合（「updated_at < 1285858800」で1件ヒットし、閾値を越える）は、たとえ完全一致検索で1件もヒットしない場合でも部分一致検索などを行いません。:

    select Blogs --filter 'updated_at < 1285858800 && body @ "東京都"'

    そのため、条件の順序を変えると検索結果が変わるという状況が発生します。以下で、この情報を回避する方法を2種類紹介しますが、それぞれトレードオフとなる条件があるので採用するかどうかを十分検討してください。

  対策方法1: トークナイザーを変更する

TokenMecabトークナイザーは事前に準備した辞書を用いてトークナイズするため、再現率よりも適合率を重視したトークナイザーと言えます。一方、TokenBigramなど、N-gram系のトークナイザーは適合率を重視したトークナイザーと言えます。例えば、TokenMecabの場合「東京都」で「京都」に完全一致することはありませんが、TokenBigramでは完全一致します。一方、TokenMecabでは「東京都民」に完全一致しませんが、TokenBigramでは完全一致します。

このようにN-gram系のトークナイザーを指定することにより再現率をあげることができますが、適合率が下がり検索ノイズが含まれる可能性が高くなります。この度合いを調整するためには /reference/commands/select のmatch_columnsで使用する索引毎に重み付けを指定します。

ここでも、前述の例を使って具体例を示します。まず、TokenBigramを用いた索引を追加します。:

table_create Bigram TABLE_PAT_KEY|KEY_NORMALIZE ShortText --default_tokenizer TokenBigram
column_create Bigram blog_body COLUMN_INDEX|WITH_POSITION Blogs body

この状態でも以前はマッチしなかったレコードがヒットするようになります。:

> select Blogs --filter 'updated_at < 1285858800 && body @ "東京都"'
[[0,7163.448064902,0.000418127],[[[1],[["_id","UInt32"],["updated_at","Time"],["body","ShortText"]],[1,1285031914.0,"東京都民に深刻なダメージを与えました。"]]]]

しかし、N-gram系のトークナイザーの方がTokenMecabトークナイザーよりも語のヒット数が多いため、N-gram系のヒットスコアの方が重く扱われてしまいます。N-gram系のトークナイザーの方がTokenMecabトークナイザーよりも適合率の低い場合が多いので、このままでは検索ノイズが上位に表示される可能性が高くなります。

そこで、TokenMecabトークナイザーを使って作った索引の方をTokenBigramトークナイザーを使って作った索引よりも重視するように重み付けを指定します。これは、match_columnsオプションで指定できます。:

> select Blogs --match_columns 'Terms.blog_body * 10 || Bigram.blog_body * 3' --query '東京都' --output_columns '_score, body'
[[0,8167.364602632,0.000647003],[[[1],[["_score","Int32"],["body","ShortText"]],[13,"東京都民に深刻なダメージを与えました。"]]]]

この場合はスコアが11になっています。内訳は、Terms.blog_body索引（TokenMecabトークナイザーを使用）でマッチしたので10、Bigram.blog_body索引（TokenBigramトークナイザーを使用）でマッチしたので3、これらを合計して13になっています。このようにTokenMecabトークナイザーの重みを高くすることにより、検索ノイズが上位にくることを抑えつつ再現率を上げることができます。

この例は日本語だったのでTokenBigramトークナイザーでよかったのですが、アルファベットの場合はTokenBigramSplitSymbolAlphaトークナイザーなども利用する必要があります。例えば、「楽しいbilliard」はTokenBigramトークナイザーでは 楽し / しい / billiard

となり、「bill」では完全一致しません。一方、TokenBigramSplitSymbolAlphaトークナイザーを使うと 楽し / しい / いb / bi / il / ll / li / ia / ar / rd / d

となり、「bill」でも完全一致します。

TokenBigramSplitSymbolAlphaトークナイザーを使う場合も重み付けを考慮する必要があることはかわりありません。

利用できるバイグラム系のトークナイザーの一覧は以下の通りです。

•   TokenBigram: バイグラムでトークナイズする。連続する記号・アルファベット・数字は一語として扱う。

•   TokenBigramSplitSymbol: 記号もバイグラムでトークナイズする。連続するアルファベット・数字は一語として扱う。

•   TokenBigramSplitSymbolAlpha: 記号とアルファベットもバイグラムでトークナイズする。連続する数字は一語として扱う。

•   TokenBigramSplitSymbolAlphaDigit: 記号・アルファベット・数字もバイグラムでトークナイズする。

•   TokenBigramIgnoreBlank: バイグラムでトークナイズする。連続する記号・アルファベット・数字は一語として扱う。空白は無視する。

•   TokenBigramIgnoreBlankSplitSymbol: 記号もバイグラムでトークナイズする。連続するアルファベット・数字は一語として扱う。空白は無視する。

•   TokenBigramIgnoreBlankSplitSymbolAlpha: 記号とアルファベットもバイグラムでトークナイズする。連続する数字は一語として扱う。空白は無視する。

•   TokenBigramIgnoreBlankSplitSymbolAlphaDigit: 記号・アルファベット・数字もバイグラムでトークナイズする。空白は無視する。

  対策方法2: 閾値をあげる

非わかち書き検索・部分一致検索を利用するかどうかの閾値は--with-match-escalation-threshold configureオプションで変更することができます。以下のように指定すると、100件以下のヒット数であれば、たとえ完全一致検索でヒットしても、非わかち書き検索・部分一致検索を行います。:

% ./configure --with-match-escalation-threashold=100

この場合も対策方法1同様、検索ノイズが上位に現れる可能性が高くなることに注意してください。検索ノイズが多くなった場合は指定する値を低くする必要があります。

開発

このセクションではgroongaを使った開発について説明します。例えば、groongaをデータベースとして使ったアプリケーション、libgroongaを使ったライブラリ、libgroongaの言語バインディングなどを開発することがあるでしょう。

  Travis CI

このセクションでは Travis CI 上でgroongaを使う方法について説明します。Travis CIはオープンソースコミュニティ用の継続的インテグレーション（CI）サービスです。

オープンソースソフトウェアを開発しているならTravis CIを使えます。このセクションではgroonga関連の設定のみ説明します。Travis CI一般については Travis CI: Documentation を読んでください。

  設定

Travis CIは32-bit版のUbuntu 11.10を使っています。（ Travis CI: About Travis CI Environment 参照。）Travis CIにgroongaをインストールするために、groongaプロジェクトが提供しているUbuntu 11.10用のapt-lineを使えます。

.travis.yml でビルド方法を変更することができます。（ Travis CI: Conifugration your Travis CI build with .travis.yml 参照。） before_install フックまたは install フックを使います。もし、Travis CIがサポートしている言語（例えばRuby）を使ったソフトウェアの場合は before_install を使います。そうでない場合は install を使います。

以下の before_install の設定を .travis.yml に加えます:

before_install:
  - curl https://raw.github.com/groonga/groonga/master/data/travis/setup.sh | sh

before_install フックではなく install フックを使わなければいけない場合は、単に before_install: を install: に書き換えてください。

上記の設定でビルド中にgroongaを使えるようになります。

  例

Travis CI上でgroongaを使っているオープンソースソフトウェアは以下の通りです

•   rroonga （Rubyバインディング）

•   Travis CIでのrroongaのビルド結果

•   rroonga用の.travis.yml

•   nroonga （node.jsバインディング）

•   Travis CIでのnroongaのビルド結果

•   nroonga用の.travis.yml

•   logaling-command (A glossary management command line tool)

•   Travis CIでのlogaling-commandのビルド結果

•   logaling-command用の.travis.yml

GROONGAへのコントリビュート方法

groongaプロジェクトではみなさんからのコントリビュートを歓迎します！コントリビュートの方法はいくつもあります。groongaを使ったり誰かに紹介することもコントリビュートですし、バグレポートを送ったり、groonga本体やgroonga関連の開発に参加することもコントリビュートです。プログラムではなく、ドキュメントでのコントリビュートも歓迎します！

ユーザーの立場で:
    このドキュメントを読んでください。

布教する立場で:
    groongaについてまわりの人に話してください。

開発者の立場で: 不具合報告や開発、ドキュメント
    これらについてはこのセクションで説明します。

  バグレポートの送り方

バグレポートを送るには2つやり方があります:

•   課題追跡システムへ登録する

•   メーリングリストへ報告する

    どちらのやり方でも大丈夫です。

  課題追跡システムへ登録する

groonga用の課題追跡システム（ITS, Issue Tracking System）が2つあります。1つは Redmine でもう1つは GitHub issue tracker です。Redmineは日本語で、GitHub issue trackerは英語を使っています。どちらにバグレポートをしても大丈夫です。

  メーリングリストへ報告する

groongaプロジェクトではgroongaについて議論するための /community があります。バグを説明したメールを送ってください。

  groonga開発者向け情報

  groonga 通信アーキテクチャ

  gqtpでのアーキテクチャ

•   comが外部からの接続を受け付ける。

•   comは1スレッド。

•   comがedgeを作る。

•   edgeは接続と１対１対応。

•   edgeはctxを含む。

•   workerはthreadと１対１対応。

•   workerは上限が個定数。

•   workerは、１つのedgeと結びつくことができる。

•   edgeごとにqueueを持つ。

•   msgはcomによって、edgeのqueueにenqueueされる。 edgeがworkerに結びついていないときは、同時に、ctx_newというqueueに、msgをenqueueした対象のedgeをenqueueする。

  ドキュメント作成

  Sphinxのインストール

groongaのドキュメントは、Sphinxというツールを用いて作成されています。Sphinxは以下のように導入します。:

# aptitude install python-setuptools
# easy_install -U sphinx

  htmlの作成

以下のコマンドでhtmlが作成されます。:

% make html

  pdfの作成

groongaのドキュメントは、pdf出力することもできます。rst2pdfと、IPAフォント(IPA Gothic/IPAexGothic)が必要となります。

  rst2pdfのインストール

以下のようにしてインストールできます。:

# easy_install rst2pdf

  pdfの作成

以下のコマンドでpdfが作成されます。:

% make pdf

  クエリの実現

groongaのデータベースには大量のデータを格納し、その中から必要な部分を高速に取り出すことができます。必要な部分をgroongaのデータベースに問い合わせるためのクエリの表現と実行に関して、groongaは複数の手段を用意しています。

  クエリ実行のためのインタフェース

groongaは低機能で単純なライブラリインタフェースから、高機能で複雑なコマンドインタフェースまでいくつかの階層的なインタフェースをユーザプログラムに提供しています。

クエリ実行のためのインタフェースも階層的なインタフェースのそれぞれに対応する形で用意されています。以下に低レイヤなインタフェースから順に説明します。

  DB_API

DB_APIは、groongaデータベースを操作するための一群のC言語向けAPI関数を提供します。DB_APIはデータベースを構成する個々の部分に対する単純な操作関数を提供します。DB_APIの機能を組み合わせることによって複雑なクエリを実行することができます。後述のすべてのクエリインタフェースはDB_APIの機能を組み合わせることによって実現されています。

  grn_expr

grn_exprは、groongaデータベースに対する検索処理や更新処理のための条件を表現するためのデータ構造で、複数の条件を再帰的に組み合わせてより複雑な条件を表現することができます。grn_exprによって表現されたクエリを実行するためには、grn_table_select()関数を使用します。

  groonga実行ファイル

groongaデータベースを操作するためのコマンドインタープリタです。渡されたコマンドを解釈し、実行結果を返します。コマンドの実処理はC言語で記述されます。ユーザがC言語で定義した関数を新たなコマンドとしてgroonga実行ファイルに組み込むことができます。各コマンドはいくつかの文字列引数を受け取り、これをクエリとして解釈して実行します。引数をgrn_exprとして解釈するか、別の形式として解釈してDB_APIを使ってデータベースを操作するかはコマンド毎に自由に決めることができます。

  grn_exprで表現できるクエリ

grn_exprは代入や関数呼び出しのような様々な操作を表現できますが、この中で検索クエリを表現するgrn_exprのことを特に条件式とよびます。条件式を構成する個々の要素を関係式と呼びます。条件式は一個以上の関係式か、あるいは条件式を論理演算子で結合したものです。

論理演算子は、以下の3種類があります。

&& (論理積)
|| (論理和)
!  (否定)

関係式は、下記の11種類が用意されています。また、ユーザが定義した関数を新たな関係式として使うこともできます。

equal(==)
not_equal(!=)
less(<)
greater(>)
less_equal(<=)
greater_equal(>=)
contain()
near()
similar()
prefix()
suffix()

  grn_table_select()

grn_table_select()関数は、grn_exprで表現された検索クエリを実行するときに使います。引数として、検索対象となるテーブル、クエリを表すgrn_expr、検索結果を格納するテーブル、それに検索にマッチしたレコードを検索結果にどのように反映するかを指定する演算子を渡します。演算子と指定できるのは下記の4種類です。

GRN_OP_OR
GRN_OP_AND
GRN_OP_BUT
GRN_OP_ADJUST

GRN_OP_ORは、検索対象テーブルの中からクエリにマッチするレコードを検索結果テーブルに加えます。GRN_OP_OR以外の演算子は、検索結果テーブルが空でない場合にだけ意味を持ちます。GRN_OP_ANDは、検索結果テーブルの中からクエリにマッチしないレコードを取り除きます。GRN_OP_BUTは、検索結果テーブルの中からクエリにマッチするレコードを取り除きます。GRN_OP_ADJUSTは、検索結果テーブルの中でクエリにマッチするレコードに対してスコア値の更新のみを行います。

grn_table_select()は、データベース上に定義されたテーブルや索引などを組み合わせて可能な限り高速に指定されたクエリを実行しようとします。

  関係式

関係式は、検索しようとしているデータが満たすべき条件を、指定した値の間の関係として表現します。いずれの関係式も、その関係が成り立ったときに評価されるcallback、コールバック関数に渡されるargとを引数として指定することができます。callbackが与えられず、argのみが数値で与えられた場合はスコア値の係数とみなされます。主な関係式について説明します。

  equal(v1, v2, arg, callback)

v1の値とv2の値が等しいことを表します。

  not_equal(v1, v2, arg, callback)

v1の値とv2の値が等しくないことを表します。

  less(v1, v2, arg, callback)

v1の値がv2の値よりも小さいことを表します。

  greater(v1, v2, arg, callback)

v1の値がv2の値よりも大きいことを表します。

  less_equal(v1, v2, arg, callback)

v1の値がv2の値と等しいか小さいことを表します。

  greater_equal(v1, v2, arg, callback)

v1の値がv2の値と等しいか大きいことを表します。

  contain(v1, v2, mode, arg, callback)

v1の値がv2の値を含んでいることを表します。また、v1の値が要素に分解されるとき、それぞれの要素に対して二つ目の要素が一致するためのmodeとして下記のいずれかを指定することができます。

EXACT: v2の値もv1の値と同様に要素に分解したとき、それぞれの要素が完全に一致する(デフォルト)
UNSPLIT: v2の値は要素に分解しない
PREFIX: v1の値の要素がv2の値に前方一致する
SUFFIX: v1の値の要素がv2の値に後方一致する
PARTIAL: v1の値の要素がv2の値に中間一致する

  near(v1, v2, arg, callback)

v1の値の中に、v2の値の要素が接近して含まれていることを表します。(v2には値の配列を渡します)

  similar(v1, v2, arg, callback)

v1の値とv2の値が類似していることを表します。

  prefix(v1, v2, arg, callback)

v1の値がv2の値に対して前方一致することを表します。

  suffix(v1, v2, arg, callback)

v1の値がv2の値に対して後方一致することを表します。

  クエリの実例

grn_exprを使って様々な検索クエリを表現することができます。

  検索例1

GRN_EXPR_CREATE_FOR_QUERY(ctx, table, query, var);
grn_expr_append_obj(ctx, query, contain, GRN_OP_PUSH, 1);
grn_expr_append_obj(ctx, query, column, GRN_OP_PUSH, 1);
grn_expr_append_const(ctx, query, string, GRN_OP_PUSH, 1);
grn_expr_append_op(ctx, query, GRN_OP_CALL, 3);
result = grn_table_select(ctx, table, query, NULL, GRN_OP_OR);

tableのcolumnの値がstringを含むレコードをresultに返します。columnの値が'needle in haystack'であるレコードr1と、columnの値が'haystack'であるレコードr2がtableに登録されていたとき、stringに'needle'を指定したなら、レコードr1のみがヒットします。

  検索例2

GRN_EXPR_CREATE_FOR_QUERY(ctx, table, query, var);
grn_expr_append_obj(ctx, query, contain, GRN_OP_PUSH, 1);
grn_expr_append_obj(ctx, query, column1, GRN_OP_PUSH, 1);
grn_expr_append_const(ctx, query, string, GRN_OP_PUSH, 1);
grn_expr_append_const(ctx, query, exact, GRN_OP_PUSH, 1);
grn_expr_append_const(ctx, query, score1, GRN_OP_PUSH, 1);
grn_expr_append_op(ctx, query, GRN_OP_CALL, 5);
result = grn_table_select(ctx, table, query, NULL, GRN_OP_OR);
grn_obj_close(ctx, query);
GRN_EXPR_CREATE_FOR_QUERY(ctx, table, query, var);
grn_expr_append_obj(ctx, query, contain, GRN_OP_PUSH, 1);
grn_expr_append_obj(ctx, query, column2, GRN_OP_PUSH, 1);
grn_expr_append_const(ctx, query, string, GRN_OP_PUSH, 1);
grn_expr_append_const(ctx, query, exact, GRN_OP_PUSH, 1);
grn_expr_append_const(ctx, query, score2, GRN_OP_PUSH, 1);
grn_expr_append_op(ctx, query, GRN_OP_CALL, 5);
grn_table_select(ctx, table, query, result, GRN_OP_ADJUST);
grn_obj_close(ctx, query);

tableのcolumn1の値がstringにexactモードでヒットするレコードについて得られるスコア値にscore1を積算してresultにセットします。次に、resultにセットされたレコードのうち、column2の値がstringにexactモードでヒットするレコードについては、得られたスコア値にscore2を積算したものを、元のスコア値に加えます。

  検索例3

GRN_EXPR_CREATE_FOR_QUERY(ctx, table, query, var);
grn_expr_append_obj(ctx, query, contain, GRN_OP_PUSH, 1);
grn_expr_append_obj(ctx, query, column1, GRN_OP_PUSH, 1);
grn_expr_append_const(ctx, query, string, GRN_OP_PUSH, 1);
grn_expr_append_const(ctx, query, exact, GRN_OP_PUSH, 1);
grn_expr_append_const(ctx, query, score1, GRN_OP_PUSH, 1);
grn_expr_append_op(ctx, query, GRN_OP_CALL, 5);
result = grn_table_select(ctx, table, query, NULL, GRN_OP_OR);
grn_obj_close(ctx, query);
if (grn_table_size(ctx, result) < t1) {
  GRN_EXPR_CREATE_FOR_QUERY(ctx, table, query, var);
  grn_expr_append_obj(ctx, query, contain, GRN_OP_PUSH, 1);
  grn_expr_append_obj(ctx, query, column1, GRN_OP_PUSH, 1);
  grn_expr_append_const(ctx, query, string, GRN_OP_PUSH, 1);
  grn_expr_append_const(ctx, query, partial, GRN_OP_PUSH, 1);
  grn_expr_append_const(ctx, query, score2, GRN_OP_PUSH, 1);
  grn_expr_append_op(ctx, query, GRN_OP_CALL, 3);
  grn_table_select(ctx, table, query, result, GRN_OP_OR);
  grn_obj_close(ctx, query);
}

tableのcolumn1の値がstringにexactモードでヒットするレコードについて得られるスコア値にscore1を積算してresultにセットします。得られた検索結果数がt1よりも小さい場合は、partialモードで再度検索し、ヒットしたレコードについて得られるスコア値にscore2を積算してresultに追加します。

  検索例4

GRN_EXPR_CREATE_FOR_QUERY(ctx, table, query, var);
grn_expr_append_obj(ctx, query, contain, GRN_OP_PUSH, 1);
grn_expr_append_const(ctx, query, string, GRN_OP_PUSH, 1);
grn_expr_append_obj(ctx, query, column, GRN_OP_PUSH, 1);
grn_expr_append_op(ctx, query, GRN_OP_CALL, 3);
result = grn_table_select(ctx, table, query, NULL, GRN_OP_OR);

tableのcolumnの値がstringに含まれるレコードをresultに返します。 columnの値が'needle'であるレコードr1と、columnの値が'haystack'であるレコードr2がtableに登録されていたとき、stringに'hay in haystack'を指定したなら、レコードr2のみがヒットします。

  リリース手順

  前提条件

リリース手順の前提条件は以下の通りです。

•   ビルド環境は Ubuntu 12.04 LTS(Precise Pangolin)

•   コマンドラインの実行例はzsh

    作業ディレクトリ例は以下を使用します。

•   GROONGA_DIR=$HOME/work/groonga

•   GROONGA_CLONE_DIR=$HOME/work/groonga/groonga.clean

•   GROONGA_GITHUB_COM_PATH=$HOME/work/groonga/groonga.github.com

•   CUTTER_DIR=$HOME/work/cutter

•   CUTTER_SOURCE_PATH=$HOME/work/cutter/cutter

  ビルド環境の準備

以下にgroongaのリリース作業を行うために事前にインストール しておくべきパッケージを示します。

なお、ビルド環境としては Ubuntu 12.04 LTS(Precise Pangolin)を前提として説明しているため、その他の環境では適宜読み替えて下さい。:

% sudo apt-get install -V debootstrap rinse createrepo rpm
mercurial python-docutils python-jinja2 ruby1.9.1-full mingw-w64 g++-mingw-w64 mecab libmecab-dev nsis gnupg2

rinseのバージョンが古いとCentOS 5/6パッケージのビルドを行うことができません。 別途debパッケージを以下のコマンドを実行して最新版をインストールします。:

% sudo dpkg -i rinse_1.9.2-1_all.deb

また、rubyのrakeパッケージを以下のコマンドによりインストールします。:

% sudo gem1.9.1 install rake

  パッケージ署名用秘密鍵のインポート

リリース作業ではRPMパッケージに対する署名を行います。 その際、パッケージ署名用の鍵が必要です。

groongaプロジェクトでは署名用の鍵をリリース担当者の公開鍵で暗号化してリポジトリのpackages/ディレクトリ以下へと登録しています。

リリース担当者はリポジトリに登録された秘密鍵を復号した後に鍵のインポートを以下のコマンドにて行います。:

% cd packages
% gpg --decrypt release-key-secret.asc.gpg.(担当者) > (復号した鍵
ファイル)
% gpg --import  (復号した鍵ファイル)

鍵のインポートが正常終了すると gpg --list-keys でgroongaの署名用の鍵を確認することができます。:

pub   1024R/F10399C0 2012-04-24
uid                  groonga Key (groonga Official Signing Key)
<packages@groonga.org>
sub   1024R/BC009774 2012-04-24

鍵をインポートしただけでは使用することができないため、インポートした鍵に対してtrust,signを行う必要があります。

以下のコマンドを実行して署名を行います。(途中の選択肢は省略):

% gpg --edit-key packages@groonga.org
gpg> trust
gpg> sign
gpg> save
gpg> quit

この作業は、新規にリリースを行うことになった担当者やパッケージに署名する鍵に変更があった場合などに行います。

  リリース作業用ディレクトリの作成

groongaのリリース作業ではリリース専用の環境下(コンパイルフラグ)でビルドする必要があります。

リリース時と開発時でディレクトリを分けずに作業することもできますが、誤ったコンパイルフラグでリリースしてしまう危険があります。

そのため、以降の説明では$GROONGA_DIR以下のディレクトリにリリース用の作業ディレクトリ(groonga.clean)としてソースコードをcloneしたものとして説明します。

リリース用のクリーンな状態でソースコードを取得するために$GROONGA_DIRにて以下のコマンドを実行します。:

% git clone git@github.com:groonga/groonga.git groonga.clean

この作業はリリース作業ごとに行います。

  変更点のまとめ

前回リリース時からの変更点を$GROONGA_CLONE_DIR/doc/source/news.txtにまとめます。 ここでまとめた内容についてはリリースアナウンスにも使用します。

前回リリースからの変更履歴を参照するには以下のコマンドを実行します。:

% git log -p --reverse $(git tag | tail -1)..

ログを^commitで検索しながら、以下の基準を目安として変更点を追記していきます。

含めるもの

•   ユーザへ影響するような変更

•   互換性がなくなるような変更

    含めないもの

•   内部的な変更(変数名の変更やらリファクタリング)

  groongaのウェブサイトの取得

groongaのウェブサイトのソースはgroonga同様にgithubにリポジトリを置いています。

リリース作業では後述するコマンド(make update-latest-release)にてトップページのバージョンを置き換えることができるようになっています。

groongaのウェブサイトのソースコードを$GROONGA_GITHUB_COM_PATHとして取得するためには、$GROONGA_DIRにて以下のコマンドを実行します。:

% git clone git@github.com:groonga/groonga.github.com.git

これで、$GROONGA_GITHUB_COM_PATHにgroonga.github.comのソースを取得できます。

  cutterのソースコード取得

groongaのリリース作業では、cutterに含まれるスクリプトを使用しています。

そこであらかじめ用意しておいた$HOME/work/cutterディレクトリにてcutterのソースコードを以下のコマンドにて取得します。:

% git clone git@github.com:clear-code/cutter.git

これで、$CUTTER_SOURCE_PATHディレクトリにcutterのソースを取得できます。

  configureスクリプトの生成

groongaのソースコードをcloneした時点ではconfigureスクリプトが含まれておらず、そのままmakeコマンドにてビルドすることができません。

$GROONGA_CLONE_DIRにてautogen.shを以下のように実行します。:

% sh autogen.sh

このコマンドの実行により、configureスクリプトが生成されます。

  configureスクリプトの実行

Makefileを生成するためにconfigureスクリプトを実行します。

リリース用にビルドするためには以下のオプションを指定してconfigureを実行します。:

% ./configure CFLAGS="-O0 -ggdb3" CXXFLAGS="-O0 -ggdb3" --prefix=/tmp/local --with-rsync-path="packages@packages.groonga.org:public" --with-groonga-github-com-path=$HOME/work/groonga/groonga.github.com --enable-document --with-ruby19 --with-cutter-source-path=$HOME/work/cutter/cutter

configureオプションである--with-groonga-github-com-pathにはgroongaのウェブサイトのリポジトリをcloneした場所を指定します。

configureオプションである--with-cutter-source-pathにはcutterのソースをcloneした場所を指定します。

以下のようにgroongaのソースコードをcloneした先からの相対パスを指定することもできます。:

% ./configure CFLAGS="-O0 -ggdb3" CXXFLAGS="-O0 -ggdb3" --prefix=/tmp/local --with-rsync-path="packages@packages.groonga.org:public" --with-groonga-github-com-path=../groonga.github.com --enable-document --with-ruby19 --with-cutter-source-path=../../cutter/cutter

あらかじめpackagesユーザでpackages.groonga.orgにsshログインできることを確認しておいてください。

ログイン可能であるかの確認は以下のようにコマンドを実行して行います。:

% ssh packages@packages.groonga.org

  make update-latest-releaseの実行

make update-latest-releaseコマンドでは、OLD_RELEASE_DATEに前回のリリースの日付を、NEW_RELEASE_DATEに次回リリースの日付を指定します。

2.0.2のリリースを行った際は以下のコマンドを実行しました。::

% make update-latest-release OLD_RELEASE=2.0.1 OLD_RELEASE_DATE=2012-03-29 NEW_RELEASE_DATE=2012-04-29

これにより、clone済みのgroongaのWebサイトのトップページのソース(index.html,ja/index.html)やRPMパッケージのspecファイルのバージョン表記などが更新されます。

  make update-filesの実行

ロケールメッセージの更新や変更されたファイルのリスト等を更新するために以下のコマンドを実行します。:

% make update-files

make update-filesを実行すると新規に追加されたファイルなどが各種.amファイルへとリストアップされます。

リリースに必要なファイルですので漏れなくコミットします。

  make update-poの実行

ドキュメントの最新版と各国語版の内容を同期するために、poファイルの更新を以下のコマンドにて実行します。:

% make update-po

make update-poを実行すると、doc/locale/ja/LC_MESSAGES以下の各種.poファイルが更新されます。

  poファイルの翻訳

make update-poコマンドの実行により更新した各種.poファイルを翻訳します。

翻訳結果をHTMLで確認するために、以下のコマンドを実行します。:

% make -C doc/locale/ja html
% make -C doc/locale/en html

確認が完了したら、翻訳済みpoファイルをコミットします。

  リリースタグの設定

リリース用のタグを打つには以下のコマンドを実行します。:

% make tag

  リリース用アーカイブファイルの作成

リリース用のソースアーカイブファイルを作成するために以下のコマンドを$GROONGA_CLONE_DIRにて実行します。:

% make dist

これにより$GROONGA_CLONE_DIR/groonga-(バージョン).tar.gzが作成されます。

ノート タグを打つ前にmake distを行うとversionが古いままになることがあります。 するとgroonga --versionで表示されるバージョン表記が更新されないので注意が必要です。 make distで生成したtar.gzのversionおよびversion.shがタグと一致することを確認するのが望ましいです。

  パッケージのビルド

リリース用のアーカイブファイルができたので、パッケージ化する作業を行います。

パッケージ化作業は以下の3種類を対象に行います。

•   Debian系(.deb)

•   Red Hat系(.rpm)

•   Windows系(.exe,.zip)

    パッケージのビルドではいくつかのサブタスクから構成されています。

  ビルド用パッケージのダウンロード

debパッケージのビルドに必要なパッケージをダウンロードするには以下のコマンドを実行します。:

% cd packages/apt
% make download

これにより、lucid以降の関連する.debパッケージやソースアーカイブなどがカレントディレクトリ以下へとダウンロードされます。

rpmパッケージのビルドに必要なパッケージをダウンロードするには以下のコマンドを実行します。:

% cd packages/yum
% make download

これにより、groongaやMySQLのRPM/SRPMパッケージなどがカレントディレクトリ以下へとダウンロードされます。

windowsパッケージのビルドに必要なパッケージをダウンロードするには以下のコマンドを実行します。:

% cd packages/windows
% make download

これにより、groongaのインストーラやzipアーカイブがカレントディレクトリ以下へとダウンロードされます。

sourceパッケージに必要なものをダウンロードするには以下のコマンドを実行します。:

% cd packages/source
% make download

これにより過去にリリースしたソースアーカイブ(.tar.gz)が packages/source/filesディレクトリ以下へとダウンロードされます。

  Debian系パッケージのビルド

groongaのpackages/aptサブディレクトリに移動して、以下のコマンドを実行します。:

% cd packages/apt
% make build PALALLEL=yes

make build PALALLEL=yesコマンドを実行すると、ディストリビューションのリリースとアーキテクチャの組み合わせでビルドを平行して行うことができます。

現在サポートされているのは以下の通りです。

•   squeeze i386/amd64

•   wheezy i386/amd64

•   unstable i386/amd64

•   lucid i386/amd64

•   natty i386/amd64

•   oneiric i386/amd64

•   precise i386/amd64

•   quantal i386/amd64

    正常にビルドが終了すると$GROONGA_CLONE_DIR/packages/apt/repositories配下に.debパッケージが生成されます。

    make build ではまとめてビルドできないこともあります。 その場合にはディストリビューションごとやアーキテクチャごとなど、個別にビルドすることで問題が発生している箇所を切り分ける必要があります。

    生成したパッケージへの署名を行うには以下のコマンドを実行します。:

    % make sign-packages

    リリース対象のファイルをリポジトリに反映するには以下のコマンドを実行します。:

    % make update-repository

    リポジトリにGnuPGで署名を行うために以下のコマンドを実行します。:

    % make sign-repository

  Red Hat系パッケージのビルド

groongaのpackages/yumサブディレクトリに移動して、以下のコマンドを実行します。:

% cd packages/yum
% make build PALALLES=yes

make build PALALLEL=yesコマンドを実行すると、ディストリビューションのリリースとアーキテクチャの組み合わせでビルドを平行して行うことができます。

現在サポートされているのは以下の通りです。

•   centos-5 i386/x86_64

•   centos-6 i386/x86_64

•   fedora-17 i386/x86_64

    ビルドが正常終了すると$GROONGA_CLONE_DIR/packages/yum/repositories配下にRPMパッケージが生成されます。

•   repositories/yum/centos/5/i386/Packages

•   repositories/yum/centos/5/x86_64/Packages

•   repositories/yum/centos/6/i386/Packages

•   repositories/yum/centos/6/x86_64/Packages

•   repositories/yum/fedora/17/i386/Packages

•   repositories/yum/fedora/17/x86_64/Packages

    リリース対象のRPMに署名を行うには以下のコマンドを実行します。:

    % make sign-packages

    リリース対象のファイルをリポジトリに反映するには以下のコマンドを実行します。:

    % make update-repository

  Windows用パッケージのビルド

packages/windowsサブディレクトリに移動して、以下のコマンドを実行します。:

% cd packages/windows
% make build
% make package
% make installer

make releaseを実行することでbuildからuploadまで一気に実行することができますが、途中で失敗することもあるので順に実行することをおすすめします。

make buildでクロスコンパイルを行います。 正常に終了するとdist-x64/dist-x86ディレクトリ以下にx64/x86バイナリを作成します。

make packageが正常に終了するとzipアーカイブをfilesディレクトリ以下に作成します。

make installerが正常に終了するとWindowsインストーラをfilesディレクトリ以下に作成します。

  パッケージの動作確認

ビルドしたパッケージに対しリリース前の動作確認を行います。

Debian系もしくはRed Hat系の場合には本番環境へとアップロードする前にローカルのaptないしyumのリポジトリを参照して正常に更新できることを確認します。

ここでは以下のようにrubyを利用してリポジトリをwebサーバ経由で参照できるようにします。:

% ruby1.9.1 -run -e httpd -- packages/yum/repositories (yumの場合)
% ruby1.9.1 -run -e httpd -- packages/apt/repositories (aptの場合)

  grntestの準備

grntestを実行するためにはgroongaのテストデータとgrntestのソースが必要です。

まずgroongaのソースを任意のディレクトリへと展開します。:

% tar zxvf groonga-(バージョン).tar.gz

次にgroongaのtest/functionディレクトリ以下にgrntestのソースを展開します。 つまりtest/function/grntestという名前でgrntestのソースを配置します。:

% ls test/function/grntest/
README.md  binlib  license  test

  grntestの実行方法

grntestではgroongaコマンドを明示的にしていすることができます。 後述のパッケージごとのgrntestによる動作確認では以下のようにして実行します。:

% GROONGA=(groongaのパス指定) test/function/run-test.sh

最後にgrntestによる実行結果が以下のようにまとめて表示されます。:

55 tests, 52 passes, 0 failures, 3 not checked tests.
94.55% passed.

grntestでエラーが発生しないことを確認します。

  Debian系の場合

Debian系の場合の動作確認手順は以下の通りとなります。

•   旧バージョンをchroot環境へとインストールする

•   chroot環境の/etc/hostsを書き換えてpackages.groonga.orgがホストを 参照するように変更する

•   ホストでwebサーバを起動してドキュメントルートをビルド環境のもの (repositories/apt/packages)に設定する

•   アップグレード手順を実行する

•   grntestのアーカイブを展開してインストールしたバージョンでテストを実 行する

•   grntestの正常終了を確認する

  Red Hat系の場合

Red Hat系の場合の動作確認手順は以下の通りとなります。

•   旧バージョンをchroot環境へとインストール

•   chroot環境の/etc/hostsを書き換えてpackages.groonga.orgがホストを参照するように変更する

•   ホストでwebサーバを起動してドキュメントルートをビルド環境のもの(packages/yum/repositories)に設定する

•   アップグレード手順を実行する

•   grntestのアーカイブを展開してインストールしたバージョンでテストを実行する

•   grntestの正常終了を確認する

  Windows向けの場合

•   新規インストール/上書きインストールを行う

•   grntestのアーカイブを展開してインストールしたバージョンでテストを実行する

•   grntestの正常終了を確認する

    zipアーカイブも同様にしてgrntestを実行し動作確認を行います。

  リリースアナウンスの作成

リリースの際にはリリースアナウンスを流して、groongaを広く通知します。

news.txtに変更点をまとめましたが、それを元にリリースアナウンスを作成します。

リリースアナウンスには以下を含めます。

•   インストール方法へのリンク

•   リリースのトピック紹介

•   リリース変更点へのリンク

•   リリース変更点(news.txtの内容)

    リリースのトピック紹介では、これからgroongaを使う人へアピールする点や既存のバージョンを利用している人がアップグレードする際に必要な情報を提供します。

    非互換な変更が含まれるのであれば、回避方法等の案内を載せることも重要です。

    参考までに過去のリリースアナウンスへのリンクを以下に示します。

•   [Groonga-talk] [ANN] groonga 2.0.2

•   http://sourceforge.net/mailarchive/message.php?msg_id=29195195

•   [groonga-dev,00794] [ANN] groonga 2.0.2

•   http://sourceforge.jp/projects/groonga/lists/archive/dev/2012-April/000794.html

  パッケージのアップロード

動作確認が完了し、Debian系、Red Hat系、Windows向け、ソースコードそれぞれにおいてパッケージやアーカイブのアップロードを行います。

Debian系のパッケージのアップロードには以下のコマンドを実行します。:

% cd packages/apt
% make upload

Red Hat系のパッケージのアップロードには以下のコマンドを実行します。:

% cd packages/yum
% make upload

Windows向けのパッケージのアップロードには以下のコマンドを実行します。:

% cd packages/windows
% make upload

ソースアーカイブのアップロードには以下のコマンドを実行します。:

% cd packages/source
% make upload

アップロードが正常終了すると、リリース対象のリポジトリデータやパッケージ、アーカイブ等がpackages.groonga.orgへと反映されます。

  blogroonga(ブログ)の更新

http://groonga.org/blog/ および http://groonga.org/blog/ にて公開されているリリース案内を作成します。

基本的にはリリースアナウンスの内容をそのまま記載します。

cloneしたWebサイトのソースに対して以下のファイルを新規追加します。

•   groonga.github.com/en/_post/(リリース日)-release.textile

•   groonga.github.com/ja/_post/(リリース日)-release.textile

    編集した内容をpushする前に確認したい場合にはjekyllおよびRedClothが必要です。 インストールするには以下のコマンドを実行します。:

    % sudo gem1.9.1 install jekyll RedCloth

    jekyllのインストールを行ったら、以下のコマンドでローカルにwebサーバを起動します。:

    % jekyll --server --auto

    あとはブラウザにてhttp://localhost:4000にアクセスして内容に問題がないかを確認します。

ノート 記事を非公開の状態でアップロードするには.textileファイルのpublished:をfalseに設定します。:

    ---
    layout: post.en
    title: Groonga 2.0.5 has been released
    published: false
    ---

  ドキュメントのアップロード

doc/source以下のドキュメントを更新、翻訳まで完了している状態で、ドキュメントのアップロード作業を行います。

そのためにはまず以下のコマンドを実行します。:

% make update-document

これによりcloneしておいたgroonga.github.comのdoc/locale以下に更新したドキュメントがコピーされます。

生成されているドキュメントに問題のないことを確認できたら、コミット、pushしてgroonga.orgへと反映します。

  リリースアナウンス

作成したリリースアナウンスをメーリングリストへと流します。

•   groonga-dev groonga-dev@lists.sourceforge.jp

•   Groonga-talk groonga-talk@lists.sourceforge.net

  freecode.comへリリース情報を登録

groongaプロジェクトではfreecode.comでもリリース情報を発信しています。

freecode.comのプロジェクトページは以下の通りです。 https://freecode.com/projects/groonga

プロジェクトの管理メニューから「Submit a release」をクリックし、 新規リリース情報を登録します。 https://freecode.com/projects/groonga/releases/new

ノート 投稿した内容に対するレビューが運営側で実施されるので、反映されるまでしばらく時間がかかります。

  Twitterでリリースアナウンスをする

blogroongaのリリースエントリには「リンクをあなたのフォロワーに共有する」ためのツイートボタンがあるので、そのボタンを使ってリリースアナウンスします。(画面下部に配置されている)

このボタンを経由する場合、ツイート内容に自動的にリリースタイトル(「groonga 2.0.8リリース」など)とblogroongaのリリースエントリのURLが挿入されます。

この作業はblogroongaの英語版、日本語版それぞれで行います。 あらかじめgroongaアカウントでログインしておくとアナウンスを円滑に行うことができます。

以上でリリース作業は終了です。

  リリース後にやること

リリースアナウンスを流し終えたら、次期バージョンの開発が始まります。

•   groonga プロジェクトの新規バージョン追加

•   groonga のbase_versionの更新

  groonga プロジェクトの新規バージョン追加

groonga プロジェクトの設定ページ にて新規バージョンを追加します。(例: release-2.0.6)

  groonga バージョン更新

$GROONGA_CLONE_DIRにて以下のコマンドを実行します。:

% make update-version NEW_VERSION=2.0.6

これにより$GROONGA_CLONE_DIR/base_versionが更新されるのでコミットしておきます。

ノート base_versionはtar.gzなどのリリース用のファイル名で使用します。

  ビルド時のTIPS

  ビルドを並列化したい

make build PALALLES=yesを指定するとchroot環境で並列にビルドを 実行できます。

  特定の環境向けのみビルドしたい

Debian系の場合、CODES,ARCHITECTURESオプションを明示的に指定することで、特定のリリース、アーキテクチャのみビルドすることができます。

squeezeのi386のみビルドしたい場合には以下のコマンドを実行します。:

% make build ARCHITECTURES=i386 CODES=squeeze

buildコマンド以外でも build-package-deb build-repository-debなどのサブタスクでもARCHITECTURES,CODES指定は有効です。

Red Hat系の場合、ARCHITECTURES,DISTRIBUTIONSオプションを明示的に指定することで、特定のリリース、アーキテクチャのみビルドすることができます。

fedoraのi386のみビルドしたい場合には以下のコマンドを実行します。:

% make build ARCHITECTURES=i386 DISTRIBUTIONS=fedora

buildコマンド以外でも build-in-chroot build-repository-rpmなどのサブタスクでもARCHITECTURES,DISTRIBUTIONSの指定は有効です。

centosの場合、CENTOS_VERSIONSを指定することで特定のバージョンのみビルドすることができます。

  パッケージの署名用のパスフレーズを知りたい

パッケージの署名に必要な秘密鍵のパスフレーズについては リリース担当者向けの秘密鍵を復号したテキストの1行目に記載してあります。

  テスト方法

  テスト環境の構築

  Cutterのインストール

groongaは、テストのフレームワークとして Cutter を用いています。

Cutterのインストール方法は プラットフォーム毎のCutterのインストール方法 をご覧下さい。

  lcovのインストール

カバレッジ情報を計測するためには、lcov 1.6以上が必要です。DebianやUbuntuでは以下のようにしてインストールできます。:

% sudo aptitude install -y lcov

  clangのインストール

ソースコードの静的解析を行うためには、clang(scan-build)をインストールする必要があります。DebianやUbuntuでは以下のようにしてインストールできます。:

% sudo aptitude install -y clang

  libmemcachedのインストール

memcachedのバイナリプロトコルのテストを動作させるためには、libmemcachedの導入が必要です。squeeze以降のDebianやKarmic以降のUubntuでは以下の用にしてインストールできます。:

% sudo aptitude install -y libmemcached-dev

  テストの動作

groongaのトップディレクトリで、以下のコマンドを実行します。:

make check

  カバレッジ情報

groongaのトップディレクトリで、以下のコマンドを実行します。:

make coverage

すると、coverageディレクトリ以下に、カバレッジ情報が入ったhtmlが出力されます。

カバレッジには、Lines/Functions/Branchesの3つの対象があります。それぞれ、行／関数／分岐に対応します。Functionsがもっとも重要な対象です。すべての関数がテストされるようになっていることを心がけてください。

テストがカバーしていない部分の編集は慎重に行ってください。また、テストがカバーしている部分を増やすことも重要です。

  様々なテスト

テストは、test/unitディレクトリにおいて、./run-test.shを実行することによっても行えます。run-test.shはいくつかのオプションをとります。詳細は、./run-test.sh --helpを実行しヘルプをご覧ください。

  特定のテスト関数のみテストする

特定のテスト関数(Cutterではテストと呼ぶ)のみをテストすることができます。

実行例:

% ./run-test.sh -n test_text_otoj

  特定のテストファイルのみテストする

特定のテストファイル(Cutterではテストケースと呼ぶ)のみテストすることができます。

実行例:

% ./run-test.sh -t test_string

  不正メモリアクセス・メモリリーク検出

環境変数CUTTER_CHECK_LEAKをyesと設定すると、valgrindを用いて不正メモリアクセスやメモリリークを検出しつつ、テストを動作させることができます。

run-test.shのみならず、make checkでも利用可能です。

実行例:

% CUTTER_CHECK_LEAK=yes make check

  デバッガ上でのテスト実行

環境変数CUTTER_DEBUGをyesと設定すると、テストが実行できる環境が整ったgdbが実行されます。gdb上でrunを行うと、テストの実行が開始されます。

run-test.shのみならず、make checkでも利用可能です。

実行例:

% CUTTER_DEBUG=yes make check

  静的解析

scan-buildを用いて、ソースコードの静的解析を行うことができます。scan_buildというディレクトリに解析結果のhtmlが出力されます。:

% scan-build ./configure --prefix=/usr
% make clean
% scan-build -o ./scan_build make -j4

configureは１度のみ実行する必要があります。

  ドキュメント関連のコントリビュート方法

ドキュメントツールとして Sphinx を使います。

  C API

今のところ、C APIのドキュメントはinclude/groonga.hにありますが、これをdoc/source/c-api/*.txtに移動したいと思っています。C APIのドキュメントを移動して、パッチを送ってくれるととても喜びます。

Sphinxの the C domain markup を使う予定です。

  国際化

今のところ、groongaには日本語でのドキュメントしかありません。1.2.2からgettextベースの Sphinx I18N feature を使ってドキュメントの国際化対応を始めました。この仕組みではベースの言語として英語を使い、日本語などの他の言語には英語からその言語に翻訳します。すべてのドキュメントはdoc/source/以下において、それをSphinxで処理します。

しかし、今のところ、doc/source/では日本語を使っています。そのため、まずは、doc/source/以下にある日本語のドキュメントを英語に翻訳する必要があります。ドキュメントを翻訳して、パッチを送ってくれるととても喜びます。

  翻訳の流れ

doc/source/*.txtを更新したら、翻訳を始めます。

これが翻訳の流れです:

1.  groongaのリポジトリをcloneします。

2.

3.

4.  HTMLファイルを生成します。

5.  HTMLの出力を確認します。

6.  翻訳が完了するまで、2.-4.を繰り返します。

7.  翻訳作業の成果をgroongaプロジェクトに送ってください！

    上記の流れを実行するコマンドラインです。詳細は以降のセクションで説明します。

    # Please fork https://github.com/groonga/groonga on GitHub
    % git clone https://github.com/${YOUR_GITHUB_ACCOUNT}/groonga.git
    % ./autogen.sh
    % ./configure
    % cd doc/locale/${LANGUAGE}/LC_MESSAGES # ${LANGUAGE} is language code such as 'ja'.
    % make update # *.po are updated
    % editor *.po # translate *.po # you can use your favorite editor
    % cd ..
    % make html
    % browser html/index.html # confirm translation
    % git add LC_MESSAGES/*.po
    % git commit
    % git push

  groongaリポジトリのcloneの仕方

はじめに、GitHub上のgroongaリポジトリをforkしてください。 https://github.com/groonga/groonga にアクセスして Fork ボタンを押すだけです。これで自分のgroongaリポジトリをcloneすることができます。:

% git clone https://github.com/${YOUR_GITHUB_ACCOUNT}/groonga.git

cloneした後はconfigureする必要があります。:

% cd groonga
% ./autogen.sh
% ./configure

この作業は初回セットアップ時のみだけの作業です。

以上の作業で問題があった場合は、 http://packages.groonga.org/source/groonga/ にあるソースファイルを利用してもよいです。

  .poファイルの更新の仕方

doc/locale/${LANGUAGE}/LC_MESSAGESディレクトリで make update を実行すると.poファイルを更新できます。（`${LANGUAGE}` は'ja'など自分の言語の言語コードに置き換えてください。）:

% cd doc/locale/ja/LC_MESSAGES
% make update

  .poの編集の仕方

Emacs's po-mode
    gettextに同梱されています。

Poedit

gted
    これも.po専用エディタです。Eclipseプラグインとして実装されています。

  HTMLファイルの生成方法

doc/locale/${LANGUAGE}/LC_MESSAGESディレクトリで make update を実行すると.poファイルを更新できます。（`${LANGUAGE}` は'ja'など自分の言語の言語コードに置き換えてください。）:

% cd doc/locale/ja/
% make html

全ての言語のHTMLファイルを生成するにはdoc/locale/ディレクトリで make html を実行します。:

% cd doc/locale
% make html

ノート

  HTML出力の確認の仕方

HTMLファイルはdoc/locale/${LANGUAGE}/html/以下に出力されます。（`${LANGUAGE}` は'ja'など自分の言語の言語コードに置き換えてください。）好きなブラウザで出力されたHTMLを確認してください。:

% firefox doc/locale/ja/html/index.html

  翻訳の成果の送り方

翻訳の成果はGitHubのpull requestかメールで送ってください。メールで送る場合はパッチでも.poファイルそのものでも構いません。

  pull requestの送り方

pull requestを送るためのコマンドライン:

% git add doc/locale/ja/LC_MESSAGES/*.po
% git commit
% git push

これでGitHub上でpull requestを送る準備ができました。あとは、GitHub上の自分のリポジトリのページへアクセスして Pull Request ボタンを押すだけです。 pull requestの送り方

  パッチの送り方

パッチを作るためのコマンドライン

% git add doc/locale/ja/LC_MESSAGES/*.po
% git commit
% git format-patch origin/master

カレントディレクトリに000X-YYY.patchという名前のファイルができていると思います。これをgroongaプロジェクトに送ってください！

  .poファイルの送り方

doc/locale/${LANGUAGE}/LC_MESSAGES/以下を.tar.gzや.zipなどでアーカイブにしてgroongaプロジェクトに送ってください！（`${LANGUAGE}` は'ja'など自分の言語の言語コードに置き換えてください。）こちらでアーカイブの中の内容をマージします。

  新しい言語の追加方法

新しい翻訳対象の言語を追加するコマンドライン:

% cd doc/locale
% make add LOCALE=${LANGUAGE} # specify your language code such as 'de'.

${LANGUAGE} は'ja'などの自分の言語の言語コードに置き換えてください。 言語名を表記するためのコード

•   genindex

•   modindex

•   search

AUTHOR
groonga project

COPYRIGHT
2009-2013, Brazil, Inc