全文検索ライブラリGroonga
=========================

Groonga は組み込み型の全文検索エンジンライブラリです。DBMSやスクリプト言語処理
系等に組み込むことによって、その全文検索機能を強化することができます。また、リ
レーショナルモデルに基づくデータストア機能を内包しており、Groonga単体でも高速
なデータストアサーバとして使用することができます。

特徴
----

■全文検索方式

転置索引型の全文検索エンジンです。転置索引は圧縮されてファイルに格納され、検索
時のディスク読み出し量を小さく、かつ局所的に抑えるように設計されています。用途
に応じて以下の索引タイプを選択できます。

 ・ 転置文書索引

    語が出現する文書番号のリストを索引に格納します。索引サイズが
    小さく、索引の更新が非常に高速です。ただし、フレーズ検索時に
    フォルスドロップが発生する可能性があります。タグ検索など、フ
    レーズ検索が不要な用途に特に適しています。

 ・ 完全転置索引

    語が出現する文書番号、および文書内での出現位置の完全なリスト
    を格納します。高精度な検索が実現できます。

 ・ 段落情報つき転置索引

    語が出現する文書とその文書内での段落番号も索引に格納します。
    段落単位での高精度な検索が実現できます。

 ・ 重み情報つき転置索引

    語が出現する文書とその文書内での重要度(フォントサイズなど)の
    情報も索引に格納します。XML/HTMLなどのタグつき文書を対象とす
    る高精度な検索が実現できます。

■トークナイズ方式

トークナイズ(検索対象の文書を語に分解する)処理の方式は、用途に応じて選択するこ
とができます。ビルトインのトークナイザとしては、形態素解析
(mecab),n-gram(unigram,bigram,trigram),空白区切りが用意されています。またユー
ザが作成した共有ライブラリ形式のトークナイザモジュールを実行時に組み込んで使う
ことができます。

■組み込み型

DBMSやスクリプト言語処理系等への組み込みやすさを重視しています。

Groongaはそれ自身もデータストア機能を備えていますが、必要な部品のみを選択して
利用することができます。したがって、あらかじめデータストア機能を備えているDBMS
に組み込む場合は転置索引機能のみを利用し、言語処理系に組み込む場合には必要に応
じてデータストア機能も含めて利用する、といった柔軟な構成を選択することができま
す。

転置索引を含めたデータストアのオブジェクトは、複数のスレッドおよび複数のプロセ
スで共有することができます。また、検索処理は他の処理との排他制御を挟むことなく
実行できます。したがって様々なスレッドモデル・プロセスモデルのシステムに、その
同時実行性能を妨げることなく組み込むことができます。

■即時更新

転置索引を含めたデータストアオブジェクトは、検索処理と同時に更新(追加/削除)処
理を実行することができます。更新した内容は、即座に検索結果に反映されます。頻繁
に内容が更新される文書に対して、常に最新の検索結果を返したい用途に適していま
す。

■高速大容量

Groongaは検索処理と更新処理のどちらも高速に実行できるように、また、大量の検索
要求が集中するサーバ用途で性能を発揮できるように設計されています。具体的には、
一つのオブジェクトに対して、(それが更新処理と同時であっても)複数のスレッドまた
はプロセスが同時に参照可能としています。ただし、一つのオブジェクトに対する更新
処理は同時に一つまでしか実行できません。

また、二次記憶への読み書きをバッファリングすることで、実メモリサイズを超える大
容量の文書でも急激に性能を低下させずに処理可能となっています。

■データストア機能

Groongaはリレーショナルモデルに基づくデータストア機能をもっています。データス
トアは、レコードの集まりであるテーブル、テーブルの集まりであるデータベースから
構成されます。テーブルには任意数のカラムを定義することができます。全文検索に用
いる転置索引もテーブルとカラムの組み合わせによって実現されます。適宜必要なカラ
ムを追加することによって、本文以外の書誌情報による絞り込みや分類・ソートなどの
機能を自由に表現することができます。

テーブルは、主キー管理方式によって以下の3種類から選択できます。

 ・ ハッシュテーブル

    ハッシュテーブルで主キーを管理します。キーと完全一致するレコー
    ドを非常に高速に検索することができます。

 ・ パトリシアトライ

    ハッシュテーブルに比べて完全一致検索の速度がやや遅いですが、
    前方一致検索・共通接頭辞探索などの検索が行えます。またカーソ
    ルを用いてキーの昇降順にレコードを取り出すことができます。

 ・ 主キーなし

    主キーの存在しないテーブルを管理します。レコードはID(識別子)
    によって識別します。

いずれの種類のテーブルも、永続型と一時型の2種類を選択できます。永続型のテーブ
ルは、ファイルに保存され、複数のプロセスで共有することができます。一時型のテー
ブルはメモリ上のみに存在し、プロセスの終了と共に破棄されます。

■動作環境

Linux(x86-64)を主要な対象として開発しています。

Windows-XP以降, Mac OS 10.*, FreeBSD, Solarisも将来的にサポートする予定です。

■ライセンス

Groongaはフリーソフトウェアです。あなたは、 Free Software Foundationが公表した
GNU Lesser General Public License 2.1が定める条項に従って本プログラムを再頒布
または変更することができます。

Groongaは有用とは思いますが、頒布にあたっては、市場性及び特定目的適合性につい
ての暗黙の保証を含めて、いかなる保証も行ないません。詳細については GNU Lesser
General Public License 2.1をお読みください。

■Sennaとの関係

GroongaはSennaの後継プロジェクトです。Sennaよりも柔軟性に優れたソフトウェアに
するために、APIを一新し、プロジェクト名も改めました。

Groongaはデータストア機能を備えるなど、Sennaとは機能的に大きく異なるソフトウェ
アのように見えますが、全文検索エンジンとしてのアーキテクチャはSennaの設計をそ
のまま踏襲しています。高い検索性能と更新性能などの特徴はそのまま受け継いでいま
す。

GroongaはSennaとの互換性はありませんが、GroongaのAPIを組み合わせることによっ
て、Sennaと同等の機能は全て実現することができます。

API説明
=======

概要
----

Groongaはリレーショナルモデルに基づくデータストア機能を中心としたAPIを提供しま
す。

データストアを構成する主要なオブジェクトは、db, type, table, column, procの5つ
です。

dbはtableの集合を管理するオブジェクトです。永続dbと一時dbのいずれかを選択でき
ます。

tableはレコードの集合を管理するオブジェクトです。dbと同様、永続tableと一時
tableのいずれかを選択できます。tableに含まれるレコードは、そのtableの中で一意
なIDを持ちます。

tableには複数のcolumnを定義することができます。 columnには名前と型を与えます。
column名はtableの中で一意でなければなりません。型とは、columnの値が納まるべき
範囲を意味します。数値や文字列などの基本的な型をtypeと呼びます。また、定義済み
の他のtableもcolumnの型として指定することができます。この場合、型として指定さ
れたtableのいずれかのレコードがcolumnの値となります。

int, float, textなどのtypeはdbの初期化時に自動的に定義されます。それ以外にユー
ザが自由にtypeを定義することも可能です。

ユーザが作成した共有ライブラリの関数を、dbにproc(手続き)として組み込むことがで
きます。 procは、データの更新・検索・トークナイズなどの幾つかの契機で呼び出す
ことができます。

mecab, unigram, bigram, delimitedなど、トークナイザとして指定可能ないくつかの
procはdbの初期化時に自動的に定義されます。

type, table, proc, columnはdbの中で一意なIDを持っています。

3階層のapi
----------

Groongaは、QL-API, DB-API, LOW-LEVEL-APIという3階層のAPIを提供しています。その
ほかにsnippet抽出や文字列操作などのいくつかのユーティリティAPIを提供していま
す。

QL-APIはgql(groonga query language)というクエリ言語を通してdbを操作するための
APIです。QL-APIはDB-APIの関数を使って実装されています。

DB-APIはtableやcolumn等のデータストアを構成するオブジェクトの個々の操作に対応
するAPIです。QL-APIを使用する場合に比べて同じ処理を記述するのにより多くのステ
ップ数が必要となりますが、QL-APIを使用するよりも高速に処理を実行できます。
DB-APIはLOW- LEVEL-APIの関数を使って実装されています。

LOW-LEVEL-APIはtableやcolumnの構成要素であるhash tableやpatricia trieなどのデ
ータ構造を直接操作するためのAPIです。LOW-LEVEL-APIを使用した場合、tableや
columnの関係はユーザが管理する必要があります。また複数の更新処理が同時に実行さ
れることを防ぐための排他制御もユーザ側で実行する必要があります。このため、
DB-APIを使用する場合に比べて同じ処理を記述するのにより多くのステップが必要とな
りますが、用途によってはDB-APIを使用するよりも高速に処理を実行できます。

■grn_ctx

ほとんどのAPI関数の第一引数にはgrn_ctxという構造体を渡します。grn_ctx構造体は次の3
つの用途に用いられます。

 ・ エラー情報の通知

    API実行中に発生したエラーのコード(enum型 grn_rcの値)、発生し
    た箇所(ソースファイル名,関数名,行番号)、エラーメッセージが
    grn_ctx構造体のメンバにセットされます。

 ・ API内部で使用するメモリの管理

    API関数は様々なオブジェクトを返します。オブジェクトには、複数
    のスレッド(またはプロセス)で共有可能なものと、grn_ctxに従属す
    るものとがあります。検索結果のレコードセットを格納する一時テー
    ブルなどは後者です。grn_ctxはこれらの一時的なオブジェクトの消
    費するメモリを管理する機能を持っています。検索処理や更新処理
    の過程で生成した一時オブジェクトは、個別に解放することも可能
    ですし、grn_ctx_fin()を呼び出すことによって一括して解放するこ
    ともできます。

 ・ QL処理系の管理

    gql(groonga query language)処理系オブジェクトは一つのgrn_ctx
    について一つだけ生成することができます。qlの実行状態は
    grn_ctxの内部で管理されます。qlを使用するかどうかはgrn_ctxの
    初期化時に選択することができます。

GroongaのAPI関数は全てリエントラントであり、マルチスレッド環境で安全に動作しま
す。しかし、APIの扱うオブジェクトの中には、複数スレッドで同時に使用可能なもの
と、そうではないものがあります。grn_ctxは後者にあたります。また、複数スレッド
での同時使用が不可能なその他のオブジェクトは、全てgrn_ctxに従属します。マルチ
スレッド環境でGroonga APIを安全に使用するためには、一つのgrn_ctxおよびgrn_ctx
に従属するオブジェクトを、複数のスレッドが同時に使用しない、という制約を守る必
要があります。

この制約を守るための簡単な手段として、スレッド固有データにgrn_ctxを保存し、ス
レッドとgrn_ctxと1:1に保つという方法が考えられます。多くのアプリケーションでこ
の方法が有効に機能するでしょう。しかし、例えば非常に多くのクライアントからの接
続を同時に受け付けるサーバシステムの中でGroongaを使用する場合には、スレッドと
grn_ctxとを動的に対応づけた方が有利かもしれません。

grn_ctx構造体は、APIを呼び出すプログラム側であらかじめ領域を確保し初期化してお
く必要があります。 grn_ctxはgrn_ctx_init()関数を使って初期化します。第1引数に
初期化対象であるgrc_ctx構造体へのポインタを指定します。第 2引数には、
GRN_CTX_USE_QL(gql処理系の要否)を指定します。grn_ctx構造体のサイズはおよそ300
バイト前後です。 grn_ctxがエラー報告のみに使用される場合、これ以上のメモリは消
費されません。grn_ctxに従属する一時オブジェクトが生成される都度、内部でメモリ
が確保されます。GRN_CTX_USE_QLを指定した場合、さらに数KByte程度のメモリが確保
されます。 grn_ctx_fin()を呼び出すとgrn_ctxとそれに従属するオブジェクトの消費
するメモリは全て解放されます。

QL-API
------

QL-APIは、gql(groonga query language)を使ってデータストアを操作するためのごく
シンプルなAPI関数です。主な操作は以下の4つだけです。

 ・ gql処理系の初期化
 ・ クエリの送信
 ・ クエリの実行結果の受信
 ・ gql処理系の終了

ライブラリを組み込んだアプリケーションのプロセス内にgql処理系を生成する方法
と、ネットワーク上に立てられたGroongaサーバに接続して Groongaサーバプロセス内
にgql処理系を生成する方法があります。初期化の手順を除けば、gql処理系がクライア
ントサイド/サーバサイドのどちら側にあっても全く同じインタフェースで操作するこ
とができます。

現時点でのgqlの実体は、Groongaバインディングを組み込んだR4RS Scheme処理系で
す。Schemeを選択した理由は、

 ・ 処理系のfootprintの小ささ
 ・ 構文木へのアクセスの容易さ

の2点にあります。両者を備えた、ユーザにとってより親しみやすい言語処理系があれ
ばそちらに移行するかもしれません。

DB-API
------

DB-APIは、Groongaデータストアを構成するオブジェクトの個々の操作に対応する関数
を提供します。以下、DB-APIを構成するオブジェクトに沿って説明します。

■grn_db

grn_dbは、tableやcolumnの名前や関係を格納し、ひとまとまりのデータストアとして
管理するオブジェクトです。grn_dbオブジェクトを作成する際に、永続(ファイルに内
容を保存する)、一時(メモリ上のみで管理)のいずれかを選択することができます。一
時dbは複数スレッドで共有して同時に使用できますが、複数プロセスで共有することは
できません。永続dbは複数プロセスおよび複数スレッドで共有して同時に使用すること
ができます。 grn_ctxは一度に一つのgrn_dbのみを使用することができます。grn_ctx
が操作対象とするgrn_dbを切り替えるときには grn_ctx_use()を使用します。複数の
grn_ctxが同一のgrn_dbを使用することができます。あるgrn_ctxを通してgrn_db に加
えられた更新操作は、即座に他のgrn_ctxからも参照可能となります。

■grn_type

データストアに格納する個々の値は、全ていずれかのデータ型に属します。データ型と
は値の範囲を決めるオブジェクトです。grn_typeは、数値や文字列などのデータ型を表
すオブジェクトです。grn_dbを作成すると、以下のgrn_typeが自動的に定義されます。

  Object
  Bool
  Int8
  UInt8
  Int16
  UInt16
  Int32
  UInt32
  Int64
  UInt64
  Float
  Time
  ShortText
  Text
  LongText
  TokyoGeoPoint
  WGS84GeoPoint

上記のgrn_typeの名前は、適宜optionを指定することによって変更することもできま
す。

ユーザが新たなgrn_typeを定義することができます。grn_typeはgrn_dbの中で一意な名
前をつける必要があります。また、その値をデータストア内で表現するのに必要なbyte
数(可変長ならば最大のbyte数)を与えます。

■grn_table

grn_tableはレコードの集合を表すオブジェクトです。grn_tableに含まれるレコードに
は、そのtableの中で一意なIDを与えられます。そのレコードが削除されない限り、レ
コードのIDが変更されることはありません。削除されたレコードのIDはその後に追加さ
れた別のレコードの IDとして再利用されます。レコードのIDは自動的に払い出され、
ユーザが指定することはできません。ただし、そのtableからレコードが削除されない
限り、レコードIDは tableにレコードを追加した順番(自然数)と一致します。

ユーザが指定するキーと対応づけてレコードを管理することもできます。キーはレコー
ドと1:1に対応し、tableの中で一意な値でなければなりません。キーには文字列や数値
などの任意のバイト列を使用することができます。キーに使用するデータの範囲はデー
タ型によって与えます。キーに指定できるデータは4Kbyte以下でなければなりません。
(<text>, <longtext>をキーとするtableを定義することはできません)

tableを作成するときに、キーの管理方式を選択することができます。

 ・ GRN_OBJ_TABLE_HASH_KEY

    ハッシュ表によってキーを管理します。レコードの追加/検索/削除
    操作を非常に高速に実行できます。

 ・ GRN_OBJ_TABLE_PAT_KEY

    パトリシアトライによってキーを管理します。
    GRN_OBJ_TABLE_HASH_KEYと比較して、レコードの追加/検索/削除操
    作の実行はやや遅くなります。前方一致検索・共通接頭辞探索など
    の検索が行えます。またカーソルを用いてキーの範囲検索を実行し、
    キー値の昇降順にレコードを取り出すことができます。また、
    GRN_OBJ_KEY_WITH_SISを合わせて指定した場合、キーの後方一致検
    索が可能になります。

 ・ GRN_OBJ_TABLE_NO_KEY

    主キーの存在しないtableを管理します。レコードはIDのみによって
    識別可能になります。

文字列を主キーとするtableの場合は、GRN_OBJ_KEY_NORMALIZEを指定すると、正規化し
た文字列がキーとなります。(符号化方式がUTF8であった場合にはUAX #15 NFKCによっ
て正規化を行います)

GRN_OBJ_PERSISTENTを指定して作られたtableはその内容がファイルに永続的に保存さ
れます。そうでなければ、tableの内容はメモリ上のみに蓄積されます。

tableを格納するgrn_dbの永続性と、tableの永続性とは独立です。一時的なgrn_dbの中
に永続的なgrn_tableを作成したり、永続的なgrn_dbの中に一時的なgrn_tableを作成す
ることも可能です。前者の場合は、tableの実体はファイルに保存されますが、その
tableの名前、キーのデータ型、他のtableとの関係などの情報は永続的には保存されま
せん。

grn_tableには、名前つきtableと無名tableの2種類があります。名前つきtableを作成
するときには、grn_dbの中で一意な名前を与えなければなりません。名前付きtable
は、複数のgrn_ctxで共有することができます。無名tableはgrn_ctxに従属し、他の
grn_ctxから操作することはできません。永続的なtableは必ず名前つきでなければなり
ません。

■grn_column

grn_tableには複数のカラム(grn_column)を作成できます。columnにはtableの中で一意
な名前と、そのcolumnに格納する値が属するデータ型を定義します。

データ型にはgrn_typeかgrn_tableを指定します。grn_tableを指定した場合は、外部参
照キーとして機能します。

grn_columnには、単一の値を格納するものと値の集合を格納するものがあります。値の
集合を格納するcolumnには以下の種類があります。

 ・ GRN_OBJ_COLUMN_ARRAY

    値の配列を格納します。

 ・ GRN_OBJ_COLUMN_SECTIONS

    重み情報つきの値の配列を格納します。配列の要素毎に32bit符号な
    し数値を付与することができます。

 ・ GRN_OBJ_COLUMN_POSTINGS

    keyとvalueのペアの集合を値として格納します。

 ・ GRN_OBJ_COLUMN_INDEX

    転置索引エントリを値として格納します。この種類のcolumnを使っ
    て高速な全文検索が実行できます。GRN_OBJ_WITH_SECTION を指定し
    た場合には、段落情報も合わせて格納します。
    GRN_OBJ_WITH_WEIGHTを指定した場合には、重み情報も合わせて格納
    します。GRN_OBJ_WITH_POSITIONを指定した場合は出現位置リストも
    合わせて格納します。

GRN_OBJ_COLUMN_INDEX以外のcolumnには、GRN_OBJ_COMPRESS_ZLIBあるいは
GRN_OBJ_COMPRESS_LZOを指定することによってデータを圧縮して保存することができま
す。

■grn_proc

grn_procは、tableやcolumnに対する参照/更新などの幾つかの契機で呼び出される手続
きに対応するオブジェクトです。転置索引を更新/検索する時に、対象の文字列をトー
クンに分解するトークナイザもgrn_procとして定義されます。grn_dbを作成すると、以
下のトークナイザprocが自動的に定義されます。

 ・ TokenDelimit : 空白で区切られた文字列をトークンとする
 ・ TokenUnigram : unigram(1文字を1トークンとする)
 ・ TokenBigram : bigram(2文字の文字列要素をトークンとする)
 ・ TokenTrigram : trigram(3文字の文字列要素をトークンとする)
 ・ TokenMecab : 形態素解析器mecabで解析した形態素をトークンとする

これ以外にも、ユーザが定義した関数をgrn_procとして組み込むことができます。ユー
ザがgrn_procを定義する場合には、init, next, finという3つの契機で呼ばれる関数を
用意します。initは手続きの実処理の最初に一度だけ呼び出されます。nextは必要に応
じて複数回呼び出されます。finは最後に一度だけ呼び出されます。それぞれの関数が
受け取る引数は、procの呼び出し契機毎に異なります。
