7.13.2. スクリプト構文 — Groonga v16.0.5ドキュメント

本文へスキップ
`Ctrl`+`K`

# 7.13.2. スクリプト構文

スクリプト構文は複雑な検索条件を指定するための構文です。この構文はECMAScriptに似ています。例えば、 `_key == "book"` は `_key` の値が `"book"` のレコードを検索するという意味です。 クエリー構文 ではすべての値は文字列でしたが、スクリプト構文では値に型があります。例えば、 `"book"` は文字列で `1` は整数で、 `TokenBigram` は `TokenBigram` という名前のオブジェクトです。

スクリプト構文はECMAScriptの構文と完全に互換性があるわけではありません。例えば、 `if` 制御文や `for` 繰り返し文や変数定義文といった文をサポートしていません。関数定義もサポートしていません。しかし、独自の演算子を追加しています。独自の演算子はECMAScriptの構文を説明した後に説明します。

## 7.13.2.1. セキュリティー

セキュリティーの観点からユーザーからの入力をそのままGroongaに渡すべきではありません。悪意のあるユーザーがそのユーザーには参照できてはいけないレコードを取得するクエリーを入力するかもしれないからです。

例えば、以下の状況を考えてみましょう。

あるGroongaアプリケーションがGroongaへのリクエストを次のようなプログラムで構築していたとします。:

    filter = "column @ \"#{user_input}\""
    select_options = {
      # ...
      :filter => filter,
    }
    groonga_client.select(select_options)

`user_input` はユーザーからの入力です。入力が `query` だった場合は構築された filter 引数は次のようになります。:

    column @ "query"

もし、入力が `x" || true || "` だった場合は構築された filter 引数は次のようになります。:

    column @ "x" || true || ""

このクエリーはすべてのレコードにマッチします。このユーザーはデータベース中のすべてのレコードを取得するでしょう。このユーザーには悪意があったのかもしれません。

ユーザーからの入力では値だけを受け取るようにする方がよいです。これは、ユーザーからの入力には `@` や `&&` のような演算子を受け付けないようにするということです。もし、演算子も受け付けるようにするなら、ユーザーは悪意のあるクエリーを作ることができます。

ユーザーの入力が値だけなら、入力された値をエスケープすることで悪意のあるクエリーを防ぐことができます。以下はユーザーの入力をどのようにエスケープすればよいかのリストです。

> - 真の値： `true` に変換してください。

> - 負の値： `false` に変換してください。

> - 数値: 整数 または 浮動小数点数 に変換してください。例えば、 `1.2` 、 `-10` 、 `314e-2` といった具合です。

> - 文字列：文字列中の `"` を `\"` で、 `\` を `\\` で置換してください。その後、置換した文字列を `"` で囲んでください。例えば、 `double " quote and back \ slash` は `"double \" quote and back \\ slash"` に変換します。

## 7.13.2.2. サンプルデータ

使い方を示すために使うスキーマ定義とサンプルデータは以下の通りです。

実行例:

    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 ShortText --default_tokenizer TokenBigram --normalizer NormalizerAuto
    # [[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` は両方とも全文検索できます。

これで例を示すためのスキーマとデータの準備ができました。

## 7.13.2.3. リテラル

### 7.13.2.3.1. 整数

整数リテラルは `1234567890` のような `0` から `9` の並びです。 `+29` や `-29` のように符号として最初に `+` または `-` をつけることができます。整数リテラルは10進数です。8進数や16進数などは使えません。

整数リテラルの最大値は `9223372036854775807` （ `= 2 ** 63 - 1` ）です。最小値は `-9223372036854775808` （ `= -(2 ** 63)` ）です。

### 7.13.2.3.2. 浮動小数点数

浮動小数点数リテラルは `3.14` のように、まず `0` から `9` 、次に `.` 、最後に `0` から `9` という並びです。 `+3.14` や `-3.14` のように符号として最初に `+` または `-` をつけることができます。 `${基数}e${指数}` や `${基数}E${指数}` というフォーマットもサポートしています。例えば、 `314e-2` は `3.14` と同じです。

### 7.13.2.3.3. 文字列

文字列リテラルは `"..."` です。リテラル中の `"` は `\"` というように `\` を前につけてエスケープします。例えば、 `"Say \"Hello!\"."` は `Say "Hello!".` という文字列のリテラルです。

文字列エンコーディングはデータベースのエンコーディングと合わせなければいけません。デフォルトのエンコーディングはUTF-8です。これは configure の `--with-default-encoding` オプションや groonga 実行ファイル の `--encoding` などで変更できます。

### 7.13.2.3.4. 真偽値

真偽値のリテラルは `true` と `false` です。 `true` は真という意味で、 `false` は偽という意味です。

### 7.13.2.3.5. NULL

NULLのリテラルは `null` です。GroongaはNULL値をサポートしてませんが、NULLリテラルをサポートしています。

### 7.13.2.3.6. 時間

注釈

これは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` になります。

### 7.13.2.3.7. 座標値

注釈

これはgroonga独自の記法です。

座標値のリテラルはありません。文字列での座標値記法を使ってください。

文字列での座標値記法には以下のパターンがあります。

> - `"ミリ秒表記の緯度xミリ秒表記の経度"`

> - `"ミリ秒表記の緯度,ミリ秒表記の経度"`

> - `"度数表記の緯度x度数表記の経度"`

> - `"度数表記の緯度,度数表記の経度"`

`x` と `,` のどちらも区切り文字として使えます。緯度と経度はミリ秒または度数で指定します。

### 7.13.2.3.8. 配列

配列リテラルは `[element1, element2, ...]` です。

### 7.13.2.3.9. オブジェクトリテラル

オブジェクトのリテラルは `{name1: value1, name2: value2, ...}` です。groongaはまだオブジェクトリテラルをサポートしていません。

## 7.13.2.4. 制御構文

スクリプト構文は文をサポートしていません。そのため、 `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` のレコードにマッチします。

## 7.13.2.5. グループ化

構文は `(...)` です。 `...` はカンマ区切りの式のリストです。

`(...)` は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"` は少なくともどちらか一方にマッチするレコードにマッチします。

## 7.13.2.6. 関数呼び出し

構文は `name(argument1, argument2, ...)` です。

`name(argument1, argument2, ...)` は `name` という関数を引数 `argument1`, `argument2`, `...` で呼び出します。

利用可能な関数の一覧は 関数 を参照してください。

以下は簡単な使用例です。

実行例:

    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
    #       ]
    #     ]
    #   ]
    # ]

この式は edit_distance を使っています。この式は `_key` カラムの値が `"Groonga"` に似ているレコードにマッチします。 `"Groonga"` との類似度は編集距離で計算します。編集距離が1文字以下なら似ているとします。この場合は `"Groonga"` と `"Mroonga"` が似ている値です。

## 7.13.2.7. 基本的な演算子

groongaはECMAScriptで定義されている演算子をサポートしています。

### 7.13.2.7.1. 算術演算子

以下は算術演算子の説明です。

#### 7.13.2.7.1.1. 加算演算子

構文は `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`) のレコードにマッチします。

#### 7.13.2.7.1.2. 減算演算子

構文は `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`) のレコードにマッチします。

#### 7.13.2.7.1.3. 乗算演算子

構文は `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`) のレコードにマッチします。

#### 7.13.2.7.1.4. 除算演算子

構文は `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`) の値にマッチします。

### 7.13.2.7.2. 論理演算子

以下は論理演算子の説明です。

#### 7.13.2.7.2.1. 論理否定演算子

構文は `!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` ではない式にマッチします。

#### 7.13.2.7.2.2. 論理積演算子

構文は `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` 以上のレコードにマッチします。

#### 7.13.2.7.2.3. 論理和演算子

構文は `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` のレコードにマッチします。

#### 7.13.2.7.2.4. 論理差演算子

構文は `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` を含んでいないレコードにマッチします。

### 7.13.2.7.3. ビット演算子

以下はビット演算子の説明です。

#### 7.13.2.7.3.1. ビット否定演算子

構文は `~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` になるからです。

#### 7.13.2.7.3.2. ビット論理積演算子

構文は `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` になるからです。

### 7.13.2.7.4. ビット論理和演算子

構文は `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`) のレコードにマッチします。

### 7.13.2.7.5. ビット排他的論理和演算子

構文は `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`) の値にマッチします。

### 7.13.2.7.6. シフト演算子

以下はシフト演算子の説明です。

#### 7.13.2.7.6.1. 左シフト演算子

構文は `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`) のレコードにマッチします。

#### 7.13.2.7.6.2. 符号付き右シフト演算子

構文は `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)`) のレコードにマッチします。

#### 7.13.2.7.6.3. 符号なし右シフト演算子

構文は `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`) のレコードにマッチします。

### 7.13.2.7.7. 比較演算子

以下は比較演算子の説明です。

#### 7.13.2.7.7.1. 等価演算子

構文は `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` の値にマッチします。

#### 7.13.2.7.7.2. 不等価演算子

構文は `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` ではない式にマッチします。

#### 7.13.2.7.7.3. 小なり演算子

TODO: ...

#### 7.13.2.7.7.4. 以下演算子

TODO: ...

#### 7.13.2.7.7.5. 大なり演算子

TODO: ...

#### 7.13.2.7.7.6. 以上演算子

TODO: ...

## 7.13.2.8. 代入演算子

### 7.13.2.8.1. 加算代入演算子

構文は `column += value` です。

この演算子は `column1` に `column2` を加算代入します。

実行例:

    select Entries --output_columns _key,n_likes,_score --filter true --scorer '_score += n_likes'
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         5
    #       ],
    #       [
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "n_likes",
    #           "UInt32"
    #         ],
    #         [
    #           "_score",
    #           "Int32"
    #         ]
    #       ],
    #       [
    #         "Good-bye Senna",
    #         3,
    #         4
    #       ],
    #       [
    #         "Good-bye Tritonn",
    #         3,
    #         4
    #       ],
    #       [
    #         "Groonga",
    #         10,
    #         11
    #       ],
    #       [
    #         "Mroonga",
    #         15,
    #         16
    #       ],
    #       [
    #         "The first post!",
    #         5,
    #         6
    #       ]
    #     ]
    #   ]
    # ]

`--filter` による `_score` の値はこの場合は常に1です。その後、'_score = _score + n_likes' という加算代入演算をそれぞれのレコードへ適用します。

例えば、 `_key` として"Good-bye Senna"を格納しているレコードの `_score` の値は3です。

そのため、 `1 + 3` という式が評価されてから `_score` カラムへと演算結果が保存されます。

### 7.13.2.8.2. 減算代入演算子

構文は `column1 -= column2` です。

この演算子は `column1` から `column2` を減算代入します。

実行例:

    select Entries --output_columns _key,n_likes,_score --filter true --scorer '_score -= n_likes'
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         5
    #       ],
    #       [
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "n_likes",
    #           "UInt32"
    #         ],
    #         [
    #           "_score",
    #           "Int32"
    #         ]
    #       ],
    #       [
    #         "Good-bye Senna",
    #         3,
    #         -2
    #       ],
    #       [
    #         "Good-bye Tritonn",
    #         3,
    #         -2
    #       ],
    #       [
    #         "Groonga",
    #         10,
    #         -9
    #       ],
    #       [
    #         "Mroonga",
    #         15,
    #         -14
    #       ],
    #       [
    #         "The first post!",
    #         5,
    #         -4
    #       ]
    #     ]
    #   ]
    # ]

`--filter` による `_score` の値はこの場合は常に1です。その後、'_score = _score - n_likes' という減算代入演算をそれぞれのレコードへ適用します。

例えば、 `_key` として"Good-bye Senna"を格納しているレコードの `_score` の値は3です。

そのため、 `1 - 3` という式が評価されてから `_score` カラムへと演算結果が保存されます。

### 7.13.2.8.3. 乗算代入演算子

構文は `column1 *= column2` です。

この演算子は `column1` に `column2` を乗算演算する。

実行例:

    select Entries --output_columns _key,n_likes,_score --filter true --scorer '_score *= n_likes'
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         5
    #       ],
    #       [
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "n_likes",
    #           "UInt32"
    #         ],
    #         [
    #           "_score",
    #           "Int32"
    #         ]
    #       ],
    #       [
    #         "Good-bye Senna",
    #         3,
    #         3
    #       ],
    #       [
    #         "Good-bye Tritonn",
    #         3,
    #         3
    #       ],
    #       [
    #         "Groonga",
    #         10,
    #         10
    #       ],
    #       [
    #         "Mroonga",
    #         15,
    #         15
    #       ],
    #       [
    #         "The first post!",
    #         5,
    #         5
    #       ]
    #     ]
    #   ]
    # ]

`--filter` による `_score` の値はこの場合は常に1です。その後、'_score = _score * n_likes' という乗算代入演算をそれぞれのレコードへ適用します。

例えば、 `_key` として"Good-bye Senna"を格納しているレコードの `_score` の値は3です。

そのため、 `1 * 3` という式が評価されてから `_score` カラムへと演算結果が保存されます。

### 7.13.2.8.4. 除算代入演算子

構文は `column1 /= column2` です。

この演算子は `column1` に `column2` を除算代入します。

実行例:

    select Entries --output_columns _key,n_likes,_score --filter true --scorer '_score /= n_likes'
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         5
    #       ],
    #       [
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "n_likes",
    #           "UInt32"
    #         ],
    #         [
    #           "_score",
    #           "Int32"
    #         ]
    #       ],
    #       [
    #         "Good-bye Senna",
    #         3,
    #         0
    #       ],
    #       [
    #         "Good-bye Tritonn",
    #         3,
    #         0
    #       ],
    #       [
    #         "Groonga",
    #         10,
    #         0
    #       ],
    #       [
    #         "Mroonga",
    #         15,
    #         0
    #       ],
    #       [
    #         "The first post!",
    #         5,
    #         0
    #       ]
    #     ]
    #   ]
    # ]

`--filter` による `_score` の値はこの場合は常に1です。その後、'_score = _score / n_likes' という除算代入演算をそれぞれのレコードへ適用します。

例えば、 `_key` として"Good-bye Senna"を格納しているレコードの `_score` の値は3です。

そのため、 `1 / 3` という式が評価されてから `_score` カラムへと演算結果が保存されます。

### 7.13.2.8.5. 剰余代入演算子

構文は `column1 %= column2` です。

この演算子は `column1` に `column2` を剰余代入します。

実行例:

    select Entries --output_columns _key,n_likes,_score --filter true --scorer '_score %= n_likes'
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         5
    #       ],
    #       [
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "n_likes",
    #           "UInt32"
    #         ],
    #         [
    #           "_score",
    #           "Int32"
    #         ]
    #       ],
    #       [
    #         "Good-bye Senna",
    #         3,
    #         1
    #       ],
    #       [
    #         "Good-bye Tritonn",
    #         3,
    #         1
    #       ],
    #       [
    #         "Groonga",
    #         10,
    #         1
    #       ],
    #       [
    #         "Mroonga",
    #         15,
    #         1
    #       ],
    #       [
    #         "The first post!",
    #         5,
    #         1
    #       ]
    #     ]
    #   ]
    # ]

`--filter` による `_score` の値はこの場合は常に1です。その後、'_score = _score % n_likes' という除算代入演算をそれぞれのレコードへ適用します。

例えば、 `_key` として"Good-bye Senna"を格納しているレコードの `_score` の値は3です。

そのため、 `1 % 3` という式が評価されてから `_score` カラムへと演算結果が保存されます。

### 7.13.2.8.6. 左シフト代入演算子

構文は `column1 << column2` です。

この演算子は `column1` のビットを左に `column2` 左ビットシフト代入演算します。

実行例:

    select Entries --output_columns _key,n_likes,_score --filter true --scorer '_score <<= n_likes'
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         5
    #       ],
    #       [
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "n_likes",
    #           "UInt32"
    #         ],
    #         [
    #           "_score",
    #           "Int32"
    #         ]
    #       ],
    #       [
    #         "Good-bye Senna",
    #         3,
    #         8
    #       ],
    #       [
    #         "Good-bye Tritonn",
    #         3,
    #         8
    #       ],
    #       [
    #         "Groonga",
    #         10,
    #         1024
    #       ],
    #       [
    #         "Mroonga",
    #         15,
    #         32768
    #       ],
    #       [
    #         "The first post!",
    #         5,
    #         32
    #       ]
    #     ]
    #   ]
    # ]

`--filter` による `_score` の値はこの場合は常に1です。その後、'_score = _score << n_likes' という左ビットシフト代入演算をそれぞれのレコードへ適用します。

例えば、 `_key` として"Good-bye Senna"を格納しているレコードの `_score` の値は3です。

そのため、 `1 << 3` という式が評価されてから `_score` カラムへと演算結果が保存されます。

### 7.13.2.8.7. 符号あり右シフト代入演算子

構文は `column1 >>= column2` です。

この演算子は `column1` のビットを `column2` 右ビットシフト代入演算します。

### 7.13.2.8.8. 符号なし右シフト代入演算子

構文は `column1 >>>= column2` です。

この演算子は `column1` のビットを `column2` 符号なし右ビットシフト代入演算します。

### 7.13.2.8.9. ビット論理積代入演算子

構文は `column1 &= column2` です。

この演算子は `column1` に `column2` をビット論理積代入演算します。

実行例:

    select Entries --output_columns _key,n_likes,_score --filter true --scorer '_score &= n_likes'
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         5
    #       ],
    #       [
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "n_likes",
    #           "UInt32"
    #         ],
    #         [
    #           "_score",
    #           "Int32"
    #         ]
    #       ],
    #       [
    #         "Good-bye Senna",
    #         3,
    #         1
    #       ],
    #       [
    #         "Good-bye Tritonn",
    #         3,
    #         1
    #       ],
    #       [
    #         "Groonga",
    #         10,
    #         0
    #       ],
    #       [
    #         "Mroonga",
    #         15,
    #         1
    #       ],
    #       [
    #         "The first post!",
    #         5,
    #         1
    #       ]
    #     ]
    #   ]
    # ]

`--filter` による `_score` の値はこの場合は常に1です。その後、'_score = _score & n_likes' というビット論理積代入演算をそれぞれのレコードへ適用します。

例えば、 `_key` として"Groonga"を格納しているレコードの値は10です。

そのため、 `1 & 10` という式が評価されてから `_score` カラムへと演算結果が保存されます。

### 7.13.2.8.10. ビット論理和代入演算子

構文は `column1 |= column2` です。

この演算子は `column1` に `column2` をビット論理和代入演算する。

実行例:

    select Entries --output_columns _key,n_likes,_score --filter true --scorer '_score |= n_likes'
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         5
    #       ],
    #       [
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "n_likes",
    #           "UInt32"
    #         ],
    #         [
    #           "_score",
    #           "Int32"
    #         ]
    #       ],
    #       [
    #         "Good-bye Senna",
    #         3,
    #         3
    #       ],
    #       [
    #         "Good-bye Tritonn",
    #         3,
    #         3
    #       ],
    #       [
    #         "Groonga",
    #         10,
    #         11
    #       ],
    #       [
    #         "Mroonga",
    #         15,
    #         15
    #       ],
    #       [
    #         "The first post!",
    #         5,
    #         5
    #       ]
    #     ]
    #   ]
    # ]

`--filter` による `_score` の値はこの場合は常に1です。その後、'_score = _score | n_likes' というビット論理和代入演算をそれぞれのレコードへ適用します。

例えば、 `_key` として"Groonga"を格納しているレコードの値は10です。

そのため、 `1 | 10` という式が評価されてから `_score` カラムへと演算結果が保存されます。

### 7.13.2.8.11. ビット排他的論理和代入演算子

構文は `column1 ^= column2` です。

この演算子は `column1` に `column2` をビット論理和代入演算する。

実行例:

    select Entries --output_columns _key,n_likes,_score --filter true --scorer '_score ^= n_likes'
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         5
    #       ],
    #       [
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "n_likes",
    #           "UInt32"
    #         ],
    #         [
    #           "_score",
    #           "Int32"
    #         ]
    #       ],
    #       [
    #         "Good-bye Senna",
    #         3,
    #         2
    #       ],
    #       [
    #         "Good-bye Tritonn",
    #         3,
    #         2
    #       ],
    #       [
    #         "Groonga",
    #         10,
    #         11
    #       ],
    #       [
    #         "Mroonga",
    #         15,
    #         14
    #       ],
    #       [
    #         "The first post!",
    #         5,
    #         4
    #       ]
    #     ]
    #   ]
    # ]

`--filter` による `_score` の値はこの場合は常に1です。その後、'_score = _score ^ n_likes' という減算代入演算をそれぞれのレコードへ適用します。

例えば、 `_key` として"Good-bye Senna"を格納しているレコードの `_score` の値は3です。

そのため、 `1 ^ 3` という式が評価されてから `_score` カラムへと演算結果が保存されます。

## 7.13.2.9. 独自の演算子

スクリプト構文はECMAScriptの構文に独自の二項演算子を追加しています。これらは検索に特化した操作をします。演算子の最初の文字は `@` または `*` です。

### 7.13.2.9.1. マッチ演算子

構文は `column @ value` です。

この演算子は `column` の転置インデックスを使って `value` を検索します。普通は全文検索をしますが、タグ検索もできます。これは、タグ検索も転置インデックスを使って実現しているからです。

クエリー構文 はデフォルトでこの演算子を使っています。

以下は簡単な使用例です。

実行例:

    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` という単語を含んでいるレコードにマッチします。

### 7.13.2.9.2. 前方一致検索演算子

構文は `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 Senna"
    #       ],
    #       [
    #         "Good-bye Tritonn"
    #       ]
    #     ]
    #   ]
    # ]

この式は `_key` カラムの値が `Goo` で始まる単語を含むレコードにマッチします。この式には `Good-bye Senna` と `Good-bye Tritonn` がマッチします。

### 7.13.2.9.3. 後方一致検索演算子

構文は `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` カラムの値が `んが` で終わるレコードにマッチします。この場合は `ぐるんが` と `むるんが` にマッチします。

### 7.13.2.9.4. 近傍検索演算子

構文は以下のどれかです。:

    column *N "word1 word2 ..."
    column *N${MAX_INTERVAL} "word1 word2 ..."
    column *N${MAX_INTERVAL},${MAX_TOKEN_INTERVAL_1}|${MAX_TOKEN_INTERVAL_2}|... "word1 word2 ..."

2つめの形式の例は次の通りです。

    column *N29 "word1 word2 ..."
    column *N-1 "word1 word2 ..."

最初の例は近いと判断する最大距離として `29` を使うという意味です。

2つめの例は近いと判断する最大距離として `-1` を使うという意味です。 `-1` はどれだけ離れていてもよいという意味です。

3つめの形式の例は次の通りです。

    column *N10,2|3 "word1 word2 word3"
    column *N10,2 "word1 word2 word3"

最初の例は最初のトークン間の最大距離として `2` を使い、2番目のトークン間の最大距離として `3` を使うという意味です。

2番目の例は最初のトークン間の最大距離として `2` を使い、2番目のトークン間の最大距離として `-1` を使うという意味です。なぜなら省略された最大距離は `-1` として処理されるからです。

トークン（単語）間の最大距離は後で説明します。

この演算子は `word1 word2 ...` という単語で近傍検索します。近傍検索はすべての単語が含まれていてかつそれぞれが指定した順番で出現していてかつそれぞれの単語が指定した距離以内にあるレコードを検索します。

近いと判断する最大距離のデフォルトは `10` です。距離の単位はN-gram系のトークナイザーでは文字数で、形態素解析系のトークナイザーでは単語数です。

しかし、`TokenBigram` はASCIIだけの単語はトークンに分割しません。このケースでは、 `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 started to use Groonga. It's very fast!` にマッチします。 `I` と `fast` の間の単語数は7です。

二番目の式は `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です。

Added in version 12.0.1: 各トークン間の最大距離。

各トークン間の最大距離を指定することができます。デフォルトでは制限はありません。これは全体の最大距離が満たされていれば各トークン間の距離は問わないということです。

以下は最初のトークン間の最大距離として `2` を使い、2番目のトークン間の最大距離として `4` を使う例です。:

    content *N10,2|4 "a b c"

`10` は最大距離です。

トークン間の最大距離は `|` で区切ります。

これは `a x b x x x c` にマッチします。しかし、これは `a x x b c` や `a b x x x x c` にはマッチしません。なぜなら、前者は最初のトークン間の距離が `3` で `2` より大きいからです。後者は2番目のトークン間の距離が `5` で `4` より大きいからです。

以下は各トークン間の最大距離を指定する例です。

実行例:

    select Entries --filter 'content *N11,5|3 "first welcome post"'
    # [
    #   [
    #     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
    #       ]
    #     ]
    #   ]
    # ]
    select Entries --filter 'content *N11,4|3 "first welcome post"'
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         0
    #       ],
    #       [
    #         [
    #           "_id",
    #           "UInt32"
    #         ],
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "content",
    #           "Text"
    #         ],
    #         [
    #           "n_likes",
    #           "UInt32"
    #         ]
    #       ]
    #     ]
    #   ]
    # ]

1つ以上のトークン間の最大距離を省略することができます。省略されたトークン間の最大距離は `-1` として扱われます。これは `*N11,5` と `*N11,5|-1` は等しいということです。 `-1` は最大距離の制限がないという意味です。

以下は1つのトークン間の最大距離を省略する例です。

実行例:

    select Entries --filter 'content *N11,5 "first welcome post"'
    # [
    #   [
    #     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
    #       ]
    #     ]
    #   ]
    # ]
    select Entries --filter 'content *N11,5|-1 "first welcome post"'
    # [
    #   [
    #     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
    #       ]
    #     ]
    #   ]
    # ]

トークン間の最大距離を余分に指定することもできます。余分な最大距離は単に無視されます。

実行例:

    select Entries --filter 'content *N11,5|6|1|2|3 "first welcome post"'
    # [
    #   [
    #     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
    #       ]
    #     ]
    #   ]
    # ]
    select Entries --filter 'content *N11,5|6 "first welcome post"'
    # [
    #   [
    #     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
    #       ]
    #     ]
    #   ]
    # ]

### 7.13.2.9.5. 近傍フレーズ検索演算子

構文は以下のどれかです。:

    column *NP "phrase1 phrase2 ..."
    column *NP${MAX_INTERVAL} "phrase1 phrase2 ..."
    column *NP${MAX_INTERVAL},${ADDITIONAL_LAST_INTERVAL} "phrase1 phrase2 ..."
    column *NP${MAX_INTERVAL},${ADDITIONAL_LAST_INTERVAL},${MAX_PHRASE_INTERVAL_1}|${MAX_PHRASE_INTERVAL_2}|... "phrase1 phrase2 ..."

2つめの形式の例は次の通りです。

    column *NP29 "phrase1 phrase2 ..."
    column *NP-1 "phrase1 phrase2 ..."

最初の例は近いと判断する最大距離として `29` を使うという意味です。

2つめの例は近いと判断する最大距離として `-1` を使うという意味です。

最大距離は後で説明します。

3つめの形式の例は次の通りです。

    column *NP10,29 "phrase1 phrase2 ..."
    column *NP10,-1 "phrase1 phrase2 ..."

最初の例は最後の追加距離として `29` を使うという意味です。

2つめの例は最後の追加距離として `-1` を使うという意味です。

最後の追加距離は後で説明します。

Added in version 12.0.1: 各フレーズ間の最大距離。

4つめの形式の例は次の通りです。

    column *NP10,0,2|3 "phrase1 phrase2 phrase3"
    column *NP10,0,2 "phrase1 phrase2 phrase3"

最初の例は最初のトークン間の最大距離として `2` を使い、2番目のトークン間の最大距離として `3` を使うという意味です。

2番目の例は最初のトークン間の最大距離として `2` を使い、2番目のトークン間の最大距離として `-1` を使うという意味です。なぜなら省略された最大距離は `-1` として処理されるからです。

各フレーズ間の最大距離については 近傍フレーズ検索演算子 を参照してください。

この演算子は `phrase1 phrase2 ...` というフレーズで近傍フレーズ検索します。近傍フレーズ検索はすべてのフレーズが含まれていてかつそれぞれが指定した順番で出現していてかつそれぞれのフレーズが指定した距離以内にあるレコードを検索します。

近いと判断する最大距離のデフォルトは `10` です。距離の単位はN-gram系のトークナイザーでは文字数で、形態素解析系のトークナイザーでは単語数です。

しかし、`TokenBigram` はASCIIだけの単語はトークンに分割しません。このケースでは、 `TokenBigram` はASCIIの文字には空白区切りのようなトークナイズ方法を使うためです。

このため、 `TokenBigram` はN-gram系のトークナイザーですが、ASCIIだけの単語を扱う時の単位は単語数になります。

`column` 用の全文検索用インデックスカラムを定義しておく必要があることに注意してください。

TODO: Use index that has `TokenNgram("unify_alphabet", false)` tokenizer to show difference with near search with English text.

以下は簡単な使用例です。

実行例:

    select Entries --filter 'content *NP "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 *NP "I Really"'    --output_columns content
    # [[0,1337566253.89858,0.000355720520019531],[[[0],[["content","Text"]]]]]
    select Entries --filter 'content *NP "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です。

2番目の式は `I` と `Really` が含まれていて、かつ、これらの単語が10単語以内近くにあるレコードにマッチします。そのため、 `I also started to use mroonga. It's also very fast! Really fast!` はマッチしません。 `I` と `Really` の間の単語数は14です。

三番目の式は `also` と `Really` が含まれていて、かつ、これらの単語が10単語以内近くにあるレコードにマッチします。そのため、 `I also started to use mroonga. It's also very fast! Really fast!` にマッチします。 `also` と `Really` の間の単語数は10です。

以下は1つの最大距離をカスタマイズする例です。

実行例:

    select Entries --filter 'content *NP14 "I 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!"
    #       ]
    #     ]
    #   ]
    # ]
    select Entries --filter 'content *NP-1 "I 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!"
    #       ]
    #     ]
    #   ]
    # ]

2番目の式は `I also started to use mroonga. It's also very fast! Really fast!` にマッチします。なぜなら `I` と `Really` の間の単語は14だからです。

2番目の式も `I also started to use mroonga. It's also very fast! Really fast!` にマッチします。なぜなら `-1` は `I` と `Really` の間にいくつ単語があってもよいという意味だからです。

最後のフレーズにだけ距離を追加することができます。つまり、最後から2番目のフレーズと最後のフレーズの間だけより多くの距離を許容できるということです。これは同一文内での近傍フレーズ検索を実装するときに便利です。最後のフレーズとして `。` （文末のフレーズ）を指定し、最後の追加距離として `-1` を指定すると、 `。` の前に他のすべてのフレーズが出現しなければいけません。最後のフレーズには `。$` というように最後に `$` をつけなければいけません。

以下は指定されたフレーズ群の最後の追加距離として `-1` を使う例です。:

    column *NP10,-1 "a b .$"

以下は指定したフレーズ群の最後の追加距離をカスタマイズする例です。

実行例:

    select Entries --filter 'content *NP1,-1 "I started .$"' --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!"
    #       ]
    #     ]
    #   ]
    # ]

最後の追加距離に正の数を指定することもできます。最後の追加距離に正の数を指定した場合、次のすべての条件を満たす必要があります。

1. 最初のフレーズと最後から2番目のフレーズの距離は `最大距離` 以下でなければいけない。

2. 最初のフレーズと最後のフレーズの距離は `最大距離` + `最後の追加距離` 以下でなければいけない。

最後の追加距離に負の数を指定した場合は2番目の条件を満たさなくてもよいです。最後のフレーズが出現するだけでよいです。

以下は最後の追加距離として正の数を指定する例です。

実行例:

    select Entries --filter 'content *NP1,4 "I started .$"' --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!"
    #       ]
    #     ]
    #   ]
    # ]

### 7.13.2.9.6. 近傍フレーズ直積検索演算子

Added in version 11.1.1.

構文は以下のどれかです。:

    column *NPP "(phrase1-1 phrase1-2 ...) (phrase2-1 phrase2-2 ...) ..."
    column *NPP${MAX_INTERVAL} "(phrase1-1 phrase1-2 ...) (phrase2-1 phrase2-2 ...) ..."
    column *NPP${MAX_INTERVAL},${ADDITIONAL_LAST_INTERVAL} "(phrase1-1 phrase1-2 ...) (phrase2-1 phrase2-2 ...) ..."
    column *NPP${MAX_INTERVAL},${ADDITIONAL_LAST_INTERVAL},${MAX_PHRASE_INTERVAL_1}|${MAX_PHRASE_INTERVAL_2}|... "(phrase1-1 phrase1-2 ...) (phrase2-1 phrase2-2 ...) ..."

2つめの形式の例は次の通りです。

    column *NPP29 "(phrase1-1 phrase1-2 ...) (phrase2-1 phrase2-2 ...) ..."
    column *NPP-1 "(phrase1-1 phrase1-2 ...) (phrase2-1 phrase2-2 ...) ..."

最初の例は近いと判断する最大距離として `29` を使うという意味です。

2つめの例は近いと判断する最大距離として `-1` を使うという意味です。

3つめの形式の例は次の通りです。

    column *NPP10,29 "(phrase1-1 phrase1-2 ...) (phrase2-1 phrase2-2 ...) ..."
    column *NPP10,-1 "(phrase1-1 phrase1-2 ...) (phrase2-1 phrase2-2 ...) ..."

最初の例は最後の追加距離として `29` を使うという意味です。

2つめの例は最後の追加距離として `-1` を使うという意味です。

Added in version 12.0.1: 各フレーズ間の最大距離。

4つめの形式の例は次の通りです。

    column *NPP10,0,2|3 "(phrase1-1 phrase1-2 ...) (phrase2-1 phrase2-2 ...) (phrase3-1 phrase3-2 ...)"
    column *NPP10,0,2 "(phrase1-1 phrase1-2 ...) (phrase2-1 phrase2-2 ...) (phrase3-1 phrase3-2 ...)"

最初の例は最初のトークン間の最大距離として `2` を使い、2番目のトークン間の最大距離として `3` を使うという意味です。

2番目の例は最初のトークン間の最大距離として `2` を使い、2番目のトークン間の最大距離として `-1` を使うという意味です。なぜなら省略された最大距離は `-1` として処理されるからです。

各フレーズ間の最大距離については 近傍フレーズ検索演算子 を参照してください。

この演算子は複数の 近傍フレーズ検索演算子 を使います。各 近傍フレーズ検索演算子 が使うフレーズ群は `{フレーズ1-1, フレーズ1-2, ...}` と `{フレーズ2-1, フレーズ2-2, ...}` と `...` の直積として計算します。たとえば、 `column *NPP "(a b c) (d e)"` は以下のフレーズ群のリストで近傍フレーズ検索をします。

- `a d`

- `a e`

- `b d`

- `b e`

- `c d`

- `c e`

以下は簡単な使用例です。

実行例:

    select Entries \
      --filter 'content *NPP "(I It) (migrated fast)"' \
      --output_columns content
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         4
    #       ],
    #       [
    #         [
    #           "content",
    #           "Text"
    #         ]
    #       ],
    #       [
    #         "I started to use Groonga. It's very fast!"
    #       ],
    #       [
    #         "I also started to use Mroonga. It's also very fast! Really fast!"
    #       ],
    #       [
    #         "I migrated all Senna system!"
    #       ],
    #       [
    #         "I also migrated all Tritonn system!"
    #       ]
    #     ]
    #   ]
    # ]

最大距離や `$` による最後のフレーズ指定や最後の追加距離など 近傍フレーズ検索演算子 のすべての機能を使うことができます。

実行例:

    select Entries \
      --filter 'content *NPP2,-1 "(I It) (migrated fast) (.$)"' \
      --output_columns content
    # [[0,1337566253.89858,0.000355720520019531],[[[0],[["content","Text"]]]]]

これは複数の 近傍フレーズ検索演算子 よりも効率的です。

### 7.13.2.9.7. 順序付き近傍フレーズ検索演算子

Added in version 11.0.9.

構文は以下のどれかです。:

    column *ONP "phrase1 phrase2 ..."
    column *ONP${MAX_INTERVAL} "phrase1 phrase2 ..."
    column *ONP${MAX_INTERVAL},${ADDITIONAL_LAST_INTERVAL} "phrase1 phrase2 ..."
    column *ONP${MAX_INTERVAL},${ADDITIONAL_LAST_INTERVAL},${MAX_PHRASE_INTERVAL_1}|${MAX_PHRASE_INTERVAL_2}|... "phrase1 phrase2 ..."

2つめの形式の例は次の通りです。

    column *ONP29 "phrase1 phrase2 ..."
    column *ONP-1 "phrase1 phrase2 ..."

最初の例は近いと判断する最大距離として `29` を使うという意味です。

2つめの例は近いと判断する最大距離として `-1` を使うという意味です。

3つめの形式の例は次の通りです。

    column *ONP10,29 "phrase1 phrase2 ..."
    column *ONP10,-1 "phrase1 phrase2 ..."

最初の例は最後の追加距離として `29` を使うという意味です。

2つめの例は最後の追加距離として `-1` を使うという意味です。

Added in version 12.0.1: 各フレーズ間の最大距離。

4つめの形式の例は次の通りです。

    column *ONP10,0,2|3 "phrase1 phrase2 phrase3"
    column *ONP10,0,2 "phrase1 phrase2 phrase3"

最初の例は最初のトークン間の最大距離として `2` を使い、2番目のトークン間の最大距離として `3` を使うという意味です。

2番目の例は最初のトークン間の最大距離として `2` を使い、2番目のトークン間の最大距離として `-1` を使うという意味です。なぜなら省略された最大距離は `-1` として処理されるからです。

各フレーズ間の最大距離については 近傍フレーズ検索演算子 を参照してください。

この演算子は `フレーズ1` と `フレーズ2` と `...` で順序付き近傍フレーズ検索をします。順序付き近傍フレーズ検索は 近傍フレーズ検索演算子 と似ていますが順序付き近傍フレーズ検索はフレーズの順番をチェックします。たとえば、 `column *ONP "groonga mroonga pgroonga"` は `groonga mroonga rroonga pgroonga` にマッチしますが `groonga rroonga pgroonga mroonga` にはマッチしません。なぜなら後者は順序が違うからです。

以下は簡単な使用例です。

実行例:

    select Entries \
      --filter 'content *ONP "I Groonga"' \
      --output_columns content
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         1
    #       ],
    #       [
    #         [
    #           "content",
    #           "Text"
    #         ]
    #       ],
    #       [
    #         "I started to use Groonga. It's very fast!"
    #       ]
    #     ]
    #   ]
    # ]
    select Entries \
      --filter 'content *ONP "Groonga I"' \
      --output_columns content
    # [[0,1337566253.89858,0.000355720520019531],[[[0],[["content","Text"]]]]]

最大距離や最後の追加距離といった 近傍フレーズ検索演算子 のすべての機能を使えます。しかし、最後のフレーズに `$` を指定する必要はありません。クエリー内の最後のフレーズが最後のフレーズになるからです。

### 7.13.2.9.8. 順序付き近傍フレーズ直積検索演算子

Added in version 11.1.1.

構文は以下のどれかです。:

    column *ONPP "(phrase1-1 phrase1-2 ...) (phrase2-1 phrase2-2 ...) ..."
    column *ONPP${MAX_INTERVAL} "(phrase1-1 phrase1-2 ...) (phrase2-1 phrase2-2 ...) ..."
    column *ONPP${MAX_INTERVAL},${ADDITIONAL_LAST_INTERVAL} "(phrase1-1 phrase1-2 ...) (phrase2-1 phrase2-2 ...) ..."
    column *ONPP${MAX_INTERVAL},${ADDITIONAL_LAST_INTERVAL},${MAX_PHRASE_INTERVAL_1}|${MAX_PHRASE_INTERVAL_2}|... "(phrase1-1 phrase1-2 ...) (phrase2-1 phrase2-2 ...) ..."

2つめの形式の例は次の通りです。

    column *ONPP29 "(phrase1-1 phrase1-2 ...) (phrase2-1 phrase2-2 ...) ..."
    column *ONPP-1 "(phrase1-1 phrase1-2 ...) (phrase2-1 phrase2-2 ...) ..."

最初の例は近いと判断する最大距離として `29` を使うという意味です。

2つめの例は近いと判断する最大距離として `-1` を使うという意味です。

3つめの形式の例は次の通りです。

    column *ONPP10,29 "(phrase1-1 phrase1-2 ...) (phrase2-1 phrase2-2 ...) ..."
    column *ONPP10,-1 "(phrase1-1 phrase1-2 ...) (phrase2-1 phrase2-2 ...) ..."

最初の例は最後の追加距離として `29` を使うという意味です。

2つめの例は最後の追加距離として `-1` を使うという意味です。

Added in version 12.0.1: 各フレーズ間の最大距離。

4つめの形式の例は次の通りです。

    column *ONPP10,0,2|3 "(phrase1-1 phrase1-2 ...) (phrase2-1 phrase2-2 ...) (phrase3-1 phrase3-2 ...)"
    column *ONPP10,0,2 "(phrase1-1 phrase1-2 ...) (phrase2-1 phrase2-2 ...) (phrase3-1 phrase3-2 ...)"

最初の例は最初のトークン間の最大距離として `2` を使い、2番目のトークン間の最大距離として `3` を使うという意味です。

2番目の例は最初のトークン間の最大距離として `2` を使い、2番目のトークン間の最大距離として `-1` を使うという意味です。なぜなら省略された最大距離は `-1` として処理されるからです。

各フレーズ間の最大距離については 近傍フレーズ検索演算子 を参照してください。

この演算子は順序付き近傍フレーズ直積検索をします。順序付き近傍フレーズ直積検索は 近傍フレーズ直積検索演算子 と似ていますが、順序付き近傍フレーズ直積検索は 順序付き近傍フレーズ検索条件 のようにフレーズの順序をチェックします。たとえば、 `column *ONPP "(a b c) (d e)"` は `a 1 d` にマッチしますが、 `d 1 a` にはマッチしません。なぜなら後者は順序が違うからです。

以下は簡単な使用例です。

実行例:

    select Entries \
      --filter 'content *ONPP "(I It) (migrated fast) (.)"' \
      --output_columns content
    # [[0,1337566253.89858,0.000355720520019531],[[[0],[["content","Text"]]]]]

最大距離や最後の追加距離といった 近傍フレーズ検索演算子 のすべての機能を使えます。しかし、最後のフレーズに `$` を指定する必要はありません。クエリー内の最後のフレーズが最後のフレーズになるからです。

### 7.13.2.9.9. 類似文書検索演算子

構文は `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!` という内容のレコードがマッチします。

日本語の文書に対して類似文書検索を行う場合は、 `TokenMecab` を使う方が良いです。`TokenMecab` は、対象の文書をほぼ単語にトークナイズするので、類似文書検索の精度が向上するためです。

### 7.13.2.9.10. 単語抽出演算子

構文は `_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 ShortText --normalizer NormalizerAuto
    # [[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` に `NormalizerAuto` ノーマライザーが指定されています。そのため、 `Words` には `groonga` とロードしていますが `Groonga` も抽出できています。また、すべてての抽出された単語も正規化されています。

### 7.13.2.9.11. 正規表現演算子

Added in version 5.0.1.

構文は `column @~ "pattern"` です。

この演算子は正規表現 `pattern` でレコードを検索します。もし、レコードの `column` の値が `pattern` にマッチしたら、そのレコードはマッチしたということです。

`pattern` は正規表現の構文になっていなければいけません。正規表現の構文の詳細は 正規表現 を参照してください。

以下の例はパターンとして `.roonga` を使っています。このパターンは `Groonga` 、 `Mroonga` といった文字列にマッチします。

実行例:

    select Entries --filter 'content @~ ".roonga"'
    # [
    #   [
    #     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
    #       ]
    #     ]
    #   ]
    # ]

多くの場合、各レコードに対して順に正規表現を評価します。そのため、多くのレコードがある場合は遅くなるかもしれません。

いくつかのケースでは、Groongaはインデックスを使って正規表現を評価します。これはとても高速です。詳細は 正規表現 を参照してください。