# groonga - オープンソースのカラムストア機能付き全文検索エンジン

- English page

# ベクターカラム

## 概要

ベクターカラムはデータストアオブジェクトです。ベクターカラムは0個以上のスカラー値を保存できます。ざっくり言うと、スカラー値とは数値や文字列といった1つの値のことです。スカラー値の詳細は `scalar` を参照してください。

ベクターカラムのユースケースの1つはタグの保存です。ベクターカラムを使うとタグの値を複数保存できます。

スカラーカラムと同じように、ベクターカラムもインデックスを使って検索できます。各要素に重みをつけることもできます。1以上の重みがついた要素がマッチすると、重みがついていない場合よりも大きなスコアがつきます。これはベクターカラム特有の機能です。重みも保存できるベクターカラムのことは重み付きベクターカラムと呼びます。

各要素がテキストなら、各要素に対して全文検索することもできます。しかし、重みを使った場合は検索スコアが高くなりすぎることに注意してください。重み付きベクターカラムに対して全文検索をするときは注意してください。

## 使い方

ベクターカラムには3種類あります。

> - ノーマルベクターカラム

> - 参照型ベクターカラム

> - 重み付きベクターカラム

このセクションではこれらの種類の使い方について説明します。

### ノーマルベクターカラム

ノーマルベクターカラムは0個以上のスカラーデータを保存します。スカラーデータとは、例えば、数値や文字列です。

ノーマルベクターカラムは同じ型の要素だけを保存できます。型を混ぜることはできません。例えば、同じノーマルベクターカラムに数値と文字列を保存できません。

ノーマルベクターカラムは、1つのレコードが、1つのキーに対して複数の値を持っているときに便利です。タグは一番よくあるユースケースです。

#### 作り方

ノーマルベクターカラムを作るためには column_create コマンドを使います。ポイントは `COLUMN_VECTOR` フラグです。

実行例:

    table_create Bookmarks TABLE_HASH_KEY ShortText
    # [[0, 1337566253.89858, 0.000355720520019531], true]
    column_create Bookmarks tags COLUMN_VECTOR ShortText
    # [[0, 1337566253.89858, 0.000355720520019531], true]

1つのブックマークに0個以上のタグを設定できます。

#### ロード方法

JSONの配列構文で指定してベクターデータをロードします:

    [ELEMENT1, ELEMENT2, ELEMENT3, ...]

以下のデータをロードしましょう。

`_key` | `tags`
--- | ---
`http://groonga.org/` | `["groonga"]`
`http://mroonga.org/` | `["mroonga", "mysql", "groonga"]`
`http://ranguba.org/` | `["ruby", "groonga"]`

以下がデータをロードするコマンドです。

実行例:

    load --table Bookmarks
    [
    {"_key": "http://groonga.org/", "tags": ["groonga"]},
    {"_key": "http://mroonga.org/", "tags": ["mroonga", "mysql", "groonga"]},
    {"_key": "http://ranguba.org/", "tags": ["ruby", "groonga"]}
    ]
    # [[0, 1337566253.89858, 0.000355720520019531], 3]

ロードしたデータはJSONの配列構文で出力されます。

実行例:

    select Bookmarks
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         3
    #       ],
    #       [
    #         [
    #           "_id",
    #           "UInt32"
    #         ],
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "tags",
    #           "ShortText"
    #         ]
    #       ],
    #       [
    #         1,
    #         "http://groonga.org/",
    #         [
    #           "groonga"
    #         ]
    #       ],
    #       [
    #         2,
    #         "http://mroonga.org/",
    #         [
    #           "mroonga",
    #           "mysql",
    #           "groonga"
    #         ]
    #       ],
    #       [
    #         3,
    #         "http://ranguba.org/",
    #         [
    #           "ruby",
    #           "groonga"
    #         ]
    #       ]
    #     ]
    #   ]
    # ]

#### 検索方法

ノーマルベクターカラムを検索するにはインデックスを作る必要があります。

実行例:

    table_create Tags TABLE_PAT_KEY ShortText
    # [[0, 1337566253.89858, 0.000355720520019531], true]
    column_create Tags bookmark_index COLUMN_INDEX Bookmarks tags
    # [[0, 1337566253.89858, 0.000355720520019531], true]

ベクターカラム固有の方法はありません。スカラーカラムにインデックスを作る方法と同じです。

全文検索と同じ構文で `tags` 内の要素を検索できます。

match_columns と query を使った場合:

実行例:

    select Bookmarks --match_columns tags --query mysql --output_columns _key,tags,_score
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         1
    #       ],
    #       [
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "tags",
    #           "ShortText"
    #         ],
    #         [
    #           "_score",
    #           "Int32"
    #         ]
    #       ],
    #       [
    #         "http://mroonga.org/",
    #         [
    #           "mroonga",
    #           "mysql",
    #           "groonga"
    #         ],
    #         1
    #       ]
    #     ]
    #   ]
    # ]

match_columns の中で重みを使うこともできます。

実行例:

    select Bookmarks --match_columns 'tags * 3' --query mysql --output_columns _key,tags,_score
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         1
    #       ],
    #       [
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "tags",
    #           "ShortText"
    #         ],
    #         [
    #           "_score",
    #           "Int32"
    #         ]
    #       ],
    #       [
    #         "http://mroonga.org/",
    #         [
    #           "mroonga",
    #           "mysql",
    #           "groonga"
    #         ],
    #         3
    #       ]
    #     ]
    #   ]
    # ]

filter を使った場合:

実行例:

    select Bookmarks --filter 'tags @ "msyql"' --output_columns _key,tags,_score
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         0
    #       ],
    #       [
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "tags",
    #           "ShortText"
    #         ],
    #         [
    #           "_score",
    #           "Int32"
    #         ]
    #       ]
    #     ]
    #   ]
    # ]

### 参照型ベクターカラム

TODO

Reference vector column is space-efficient if there are many same value elements. Reference vector column keeps reference record IDs not value itself. Record ID is smaller than value itself.

#### 作り方

TODO

#### ロード方法

TODO

#### 検索方法

TODO

### 重み付きベクターカラム

重み付きベクターカラムはノーマルベクターカラムに似ています。複数の要素を保存できます。さらに、要素の重みも保存できます。重みとはその要素の重要度です。

重みは正の整数です。デフォルトの重みは `0` です。これは重みがないという意味になります。

重みが1以上なら、検索スコアーに重みが加算されます。重みが `0` なら検索スコアーは `1` です。重みが `10` なら検索スコアーは `11` （ `= 1 + 10` ）です。

重み付きベクターカラムは検索スコアーのチューニングに便利です。 adjuster も参照してください。特定のレコードの検索スコアーを増やすことができます。

#### 制限

今のところいくつか制限があります。将来的には解消される予定です。

以下が制限です。

> - ロード時に要素の値を文字列での表現で指定しなければいけません。例えば、数値の29を指定するために、 `29` を使うことはできません。 `"29"` と文字列で表記する必要があります。

> - 参照型を使うことができません。

#### 作り方

重み付きベクターカラムを作るには column_create を使います。ポイントは `COLUMN_VECTOR|WITH_WEIGHT` フラグです。

実行例:

    table_create Bookmarks TABLE_HASH_KEY ShortText
    # [[0, 1337566253.89858, 0.000355720520019531], true]
    column_create Bookmarks tags COLUMN_VECTOR|WITH_WEIGHT ShortText
    # [[0, 1337566253.89858, 0.000355720520019531], true]

`WITH_WEIGHT` フラグを指定しないと、ただのノーマルベクターカラムになります。

1つのブックマークに重み付きで0個以上のタグを設定できます。

#### ロード方法

JSONのオブジェクト構文でベクターデータをロードします:

    {"ELEMENT1": WEIGHT1, "ELEMENT2": WEIGHT2, "ELEMENT3": WEIGHT3, ...}

以下のデータをロードしましょう。

`_key` | `tags`
--- | ---
`http://groonga.org/` | `{"groonga": 100}`
`http://mroonga.org/` | `{"mroonga": 100, "mysql": 50, "groonga": 10}`
`http://ranguba.org/` | `{"ruby": 100, "groonga": 50}`

以下がデータをロードするコマンドです。

実行例:

    load --table Bookmarks
    [
    {"_key": "http://groonga.org/",
     "tags": {"groonga": 100}},
    {"_key": "http://mroonga.org/",
     "tags": {"mroonga": 100,
              "mysql":   50,
              "groonga": 10}},
    {"_key": "http://ranguba.org/",
     "tags": {"ruby": 100,
              "groonga": 50}}
    ]
    # [[0, 1337566253.89858, 0.000355720520019531], 3]

ロードしたデータはJSONのオブジェクト構文で出力されます。

実行例:

    select Bookmarks
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         3
    #       ],
    #       [
    #         [
    #           "_id",
    #           "UInt32"
    #         ],
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "tags",
    #           "ShortText"
    #         ]
    #       ],
    #       [
    #         1,
    #         "http://groonga.org/",
    #         {
    #           "groonga": 100
    #         }
    #       ],
    #       [
    #         2,
    #         "http://mroonga.org/",
    #         {
    #           "mroonga": 100,
    #           "groonga": 10,
    #           "mysql": 50
    #         }
    #       ],
    #       [
    #         3,
    #         "http://ranguba.org/",
    #         {
    #           "ruby": 100,
    #           "groonga": 50
    #         }
    #       ]
    #     ]
    #   ]
    # ]

#### 検索方法

重み付きベクターを検索するためにはインデックスを作る必要があります。 `column_create` に `WITH_WEIGHT` フラグを指定することを忘れないでください。

実行例:

    table_create Tags TABLE_PAT_KEY ShortText
    # [[0, 1337566253.89858, 0.000355720520019531], true]
    column_create Tags bookmark_index COLUMN_INDEX|WITH_WEIGHT Bookmarks tags
    # [[0, 1337566253.89858, 0.000355720520019531], true]

`WITH_WEIGHT` 以外は重み付きベクターカラムに特有の方法はありません。スカラーカラムにインデックスを作る方法と同じです。

全文検索と同じ構文で `tags` 内の要素を検索できます。

match_columns と query を使った場合:

実行例:

    select Bookmarks --match_columns tags --query groonga --output_columns _key,tags,_score
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         3
    #       ],
    #       [
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "tags",
    #           "ShortText"
    #         ],
    #         [
    #           "_score",
    #           "Int32"
    #         ]
    #       ],
    #       [
    #         "http://groonga.org/",
    #         {
    #           "groonga": 100
    #         },
    #         101
    #       ],
    #       [
    #         "http://mroonga.org/",
    #         {
    #           "mroonga": 100,
    #           "groonga": 10,
    #           "mysql": 50
    #         },
    #         11
    #       ],
    #       [
    #         "http://ranguba.org/",
    #         {
    #           "ruby": 100,
    #           "groonga": 50
    #         },
    #         51
    #       ]
    #     ]
    #   ]
    # ]

match_columns の重みと一緒に使うこともできます。スコアーは `(1 + 重み付きベクターの重み) * match_columnsの重み` 。

実行例:

    select Bookmarks --match_columns 'tags * 3' --query groonga --output_columns _key,tags,_score
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         3
    #       ],
    #       [
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "tags",
    #           "ShortText"
    #         ],
    #         [
    #           "_score",
    #           "Int32"
    #         ]
    #       ],
    #       [
    #         "http://groonga.org/",
    #         {
    #           "groonga": 100
    #         },
    #         303
    #       ],
    #       [
    #         "http://mroonga.org/",
    #         {
    #           "mroonga": 100,
    #           "groonga": 10,
    #           "mysql": 50
    #         },
    #         33
    #       ],
    #       [
    #         "http://ranguba.org/",
    #         {
    #           "ruby": 100,
    #           "groonga": 50
    #         },
    #         153
    #       ]
    #     ]
    #   ]
    # ]

filter を使った場合:

実行例:

    select Bookmarks --filter 'tags @ "groonga"' --output_columns _key,tags,_score
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         3
    #       ],
    #       [
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "tags",
    #           "ShortText"
    #         ],
    #         [
    #           "_score",
    #           "Int32"
    #         ]
    #       ],
    #       [
    #         "http://groonga.org/",
    #         {
    #           "groonga": 100
    #         },
    #         101
    #       ],
    #       [
    #         "http://mroonga.org/",
    #         {
    #           "mroonga": 100,
    #           "groonga": 10,
    #           "mysql": 50
    #         },
    #         11
    #       ],
    #       [
    #         "http://ranguba.org/",
    #         {
    #           "ruby": 100,
    #           "groonga": 50
    #         },
    #         51
    #       ]
    #     ]
    #   ]
    # ]

#### 重みだけを適用する方法

マッチしたレコード集合を変更せずに、重み付きベクターカラムの重みの分だけ検索スコアーを増やすことができます。

この用途には adjuster を使います。

実行例:

    select Bookmarks \
      --filter true \
      --adjuster 'tags @ "mysql" * 10 + tags @ "groonga" * 5' \
      --output_columns _key,tags,_score
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         3
    #       ],
    #       [
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "tags",
    #           "ShortText"
    #         ],
    #         [
    #           "_score",
    #           "Int32"
    #         ]
    #       ],
    #       [
    #         "http://groonga.org/",
    #         {
    #           "groonga": 100
    #         },
    #         506
    #       ],
    #       [
    #         "http://mroonga.org/",
    #         {
    #           "mroonga": 100,
    #           "groonga": 10,
    #           "mysql": 50
    #         },
    #         566
    #       ],
    #       [
    #         "http://ranguba.org/",
    #         {
    #           "ruby": 100,
    #           "groonga": 50
    #         },
    #         256
    #       ]
    #     ]
    #   ]
    # ]

この `select` コマンドは `--filter true` を使っています。そのため、すべてのレコードがマッチし、スコアーは1になります。それから、 `--adjuster` を適用します。アジャスターは以下のことをします。

> - `tags @ "mysql" * 10` は `"mysql"` タグを含むレコードのスコアーを `(1 + 重み) * 10` 増やします。

> - `tags @ "groonga" * 5` は `"groonga"` タグを含むレコードのスコアーを `(1 + 重み) * 5` 増やします。

例えば、 `"http://mroonga.org/"` レコードは `"mysql"` タグと `"groonga"` タグを両方持っています。そのため、スコアーは `565` （ `= ((1 + 50) * 10) + ((1 + 10) * 5) = (51 * 10) + (11 * 5) = 510 + 55` ）増えます。 `--adjuster` を適用する前は、`--filter true` によって検索スコアーは1になっています。そのため、 `"http://mroonga.org/"` レコードの最終的な検索スコアーは `566` （ `= 1 + 565` ）になります。