# 7.3.32. `logical_count`

## 7.3.32.1. 概要

バージョン 5.0.0 で追加.

`logical_count` は logical_select の件数カウント機能だけを提供するコマンドです。 logical_select は複数のテーブルからレコードを検索し、マッチしたレコード数を出力し、マッチしたレコードのカラムを出力し、他にもいろいろします。 `logical_count` は複数のテーブルからレコードを検索し、マッチしたレコード数を出力するだけです。

`logical_count` はマッチしたレコードの数だけを知りたいときに便利です。 `logical_count` と logical_range_filter を一緒に使えます。一緒に使うと、マッチしたレコード数を取得する前に、マッチしたレコードのうち先頭のNレコードだけを先に表示できます。 logical_select だけを使っている場合は、すべての検索処理が終わるまで待たなければいけません。

このコマンド は `sharding` プラグインに含まれているので、 `sharding` プラグインを plugin_register する必要があります。

## 7.3.32.2. 構文

このコマンドにはたくさんの引数があります。

必須の引数は `logical_table` と `shard_key` です。それ以外の引数は省略可能です:

    logical_count
      logical_table
      shard_key
      [min=null]
      [min_border="include"]
      [max=null]
      [max_border="include"]
      [filter=null]
      [post_filter=null]

いくつか名前付き引数としてしか使えない引数があります。これらの引数を「○番目の引数」として使うことはできません。必ず名前を指定する必要があります。

名前付き引数としてしか使えない引数は次の通りです。

> - `cache=no`

バージョン 7.0.9 で追加: 以下の名前付き引数で動的カラム機能を使うことができます。

> - `columns[${NAME}].stage=null`

> - `columns[${NAME}].flags=COLUMN_SCALAR`

> - `columns[${NAME}].type=null`

> - `columns[${NAME}].value=null`

> - `columns[${NAME}].window.sort_keys=null`

> - `columns[${NAME}].window.group_keys=null`

`${NAME}` には1つ以上のアルファベット、数字、 `_` を使うことができます。たとえば、 `column1` は有効な `${NAME}` です。これは通常のカラムと同じルールです。 name も見てください。

同じ `${NAME}` も持つ引数は同じグループになります。

たとえば、以下の引数は1つの動的カラムを指定しています。

> - `--columns[name].stage initial`

> - `--columns[name].type UInt32`

> - `--columns[name].value 29`

以下の引数は2つの動的カラムを指定しています。

> - `--columns[name1].stage initial`

> - `--columns[name1].type UInt32`

> - `--columns[name1].value 29`

> - `--columns[name2].stage initial`

> - `--columns[name2].type Float`

> - `--columns[name2].value '_score * 0.1'`

## 7.3.32.3. 使い方

例を使いながら使い方を学びましょう。このセクションではよく使われる使い方を紹介します。

このコマンドは `sharding` プラグインに含まれているので `sharding` プラグインを登録する必要があります。

実行例:

    plugin_register sharding
    # [[0, 1337566253.89858, 0.000355720520019531], true]

`logical_count` コマンドは実験的なプラグインです。このコマンドは将来的に変更されるかもしれません。

この機能を使う簡単な例を示します。複数のテーブルに保存されている特定のログをカウントしてみましょう。

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

実行例:

    table_create Entries_20150708 TABLE_HASH_KEY ShortText
    # [[0, 1337566253.89858, 0.000355720520019531], true]
    column_create Entries_20150708 created_at COLUMN_SCALAR Time
    # [[0, 1337566253.89858, 0.000355720520019531], true]
    column_create Entries_20150708 content COLUMN_SCALAR Text
    # [[0, 1337566253.89858, 0.000355720520019531], true]
    column_create Entries_20150708 n_likes COLUMN_SCALAR UInt32
    # [[0, 1337566253.89858, 0.000355720520019531], true]
    column_create Entries_20150708 tag COLUMN_SCALAR ShortText
    # [[0, 1337566253.89858, 0.000355720520019531], true]
    table_create Entries_20150709 TABLE_HASH_KEY ShortText
    # [[0, 1337566253.89858, 0.000355720520019531], true]
    column_create Entries_20150709 created_at COLUMN_SCALAR Time
    # [[0, 1337566253.89858, 0.000355720520019531], true]
    column_create Entries_20150709 content COLUMN_SCALAR Text
    # [[0, 1337566253.89858, 0.000355720520019531], true]
    column_create Entries_20150709 n_likes COLUMN_SCALAR UInt32
    # [[0, 1337566253.89858, 0.000355720520019531], true]
    column_create Entries_20150709 tag COLUMN_SCALAR ShortText
    # [[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_20150708 \
      COLUMN_INDEX|WITH_POSITION Entries_20150708 _key
    # [[0, 1337566253.89858, 0.000355720520019531], true]
    column_create Terms entries_content_index_20150708 \
      COLUMN_INDEX|WITH_POSITION Entries_20150708 content
    # [[0, 1337566253.89858, 0.000355720520019531], true]
    column_create Terms entries_key_index_20150709 \
      COLUMN_INDEX|WITH_POSITION Entries_20150709 _key
    # [[0, 1337566253.89858, 0.000355720520019531], true]
    column_create Terms entries_content_index_20150709 \
      COLUMN_INDEX|WITH_POSITION Entries_20150709 content
    # [[0, 1337566253.89858, 0.000355720520019531], true]
    load --table Entries_20150708
    [
    {"_key":       "The first post!",
     "created_at": "2015/07/08 00:00:00",
     "content":    "Welcome! This is my first post!",
     "n_likes":    5,
     "tag":        "Hello"},
    {"_key":       "Groonga",
     "created_at": "2015/07/08 01:00:00",
     "content":    "I started to use Groonga. It's very fast!",
     "n_likes":    10,
     "tag":        "Groonga"},
    {"_key":       "Mroonga",
     "created_at": "2015/07/08 02:00:00",
     "content":    "I also started to use Mroonga. It's also very fast! Really fast!",
     "n_likes":    15,
     "tag":        "Groonga"}
    ]
    # [[0, 1337566253.89858, 0.000355720520019531], 3]
    load --table Entries_20150709
    [
    {"_key":       "Good-bye Senna",
     "created_at": "2015/07/09 00:00:00",
     "content":    "I migrated all Senna system!",
     "n_likes":    3,
     "tag":        "Senna"},
    {"_key":       "Good-bye Tritonn",
     "created_at": "2015/07/09 01:00:00",
     "content":    "I also migrated all Tritonn system!",
     "n_likes":    3,
     "tag":        "Senna"}
    ]
    # [[0, 1337566253.89858, 0.000355720520019531], 2]

ブログエントリー用に `Entries_20150708` と `Entries_20150709` の2つのテーブルがあります。

注釈

テーブル名には `${論理テーブル名}_${YYYYMMDD}` という命名規則を使う必要があります。この例では、 `論理テーブル名` は `Entries` で `YYYYMMDD` は `20150708` または `20150709` です。

各エントリはタイトルと作成日時と内容と「いいね！」数、タグを持っています。タイトルは `Entries_YYYYMMDD` のキーとします。作成日時は `Entries_YYYYMMDD.created_at` カラムの値とします。内容は `Entries_YYYYMMDD.content` カラムの値とします。「いいね！」数は `Entries_YYYYMMDD.n_likes` カラムの値とします。タグは `Entries_YYYYMMDD.tag` カラムの値とします。

`Entries_YYYYMMDD._key` カラムと `Entries_YYYYMMDD.content` カラムには `TokenBigram` トークナイザーを使ったインデックスを作成します。そのため、 `Entries_YYYYMMDD._key` と `Entries_YYYYMMDD.content` は両方とも全文検索できます。

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

以下は `content` カラムに `Groonga` または `Senna` を含むレコード数を数える例です。 `logical_count` はすべての `Entries_YYYYMMDD` テーブルを検索します。

実行例:

    logical_count \
      --logical_table Entries \
      --shard_key created_at \
      --filter 'query("content", "Groonga OR Senna")'
    # [[0, 1337566253.89858, 0.000355720520019531], 2]

マッチしたレコードは次の通りです。

> - `Entries_20150708` の中の `_key:"Groonga"`

> - `Entries_20150709` の中の `_key:"Good-bye Senna"`

## 7.3.32.4. 引数

このセクションではこのコマンドのパラメーターを説明します。

### 7.3.32.4.1. 必須引数

必須引数は二つあります。 `logical_table` と `shard_key` です。

#### 7.3.32.4.1.1. `logical_table`

論理テーブル名を指定します。これは `_YYYYMMDD` をテーブル名から除いたものです。実際のテーブルが `Logs_20150203` や `Logs_20150203` といったものなら、論理テーブル名は `Logs` です。

`logical_table` と `shard_key` だけを指定すると全レコード数をカウントできます。これらの引数は必須の引数です。

実行例:

    logical_count \
      --logical_table Entries \
      --shard_key created_at
    # [[0, 1337566253.89858, 0.000355720520019531], 5]

存在しないテーブルを指定するとエラーが返ります。

実行例:

    logical_count \
      --logical_table Nonexistent \
      --shard_key created_at
    # [
    #   [
    #     -22,
    #     1337566253.89858,
    #     0.000355720520019531,
    #     "[logical_count] no shard exists: logical_table: <Nonexistent>: shard_key: <created_at>",
    #     [
    #       [
    #         "Groonga::Sharding::LogicalCountCommand.run_body",
    #         "/home/horimoto/work/release/groonga/groonga.clean/plugins/sharding/logical_count.rb",
    #         30
    #       ]
    #     ]
    #   ]
    # ]

#### 7.3.32.4.1.2. `shard_key`

シャードキーとして使うカラム名を指定します。シャードキーは適切なシャードへレコードを分配するために使う値を保存しているカラムです。

今のところ、シャードキーは `Time` 型でなければいけません。

`shard_key` の指定方法は logical_table を見てください。

### 7.3.32.4.2. 省略可能引数

いくつか省略可能な引数があります。

#### 7.3.32.4.2.1. `min`

`shard_key` カラムの最小値を指定します。シャードにマッチするレコードがない場合は、そのシャードは検索対象外になります。

たとえば、 `min` が `"2015/07/09 00:00:00"` なら、 `Entry_20150708` は検索対象外です。なぜなら、 `Entry_20150708` は `"2015/07/08"` のレコードしかないからです。

以下の例は `Entry_20150709` テーブルだけを使う例です。 `Entry_20150708` は使われません。

実行例:

    logical_count \
      --logical_table Entries \
      --shard_key created_at \
      --min "2015/07/09 00:00:00"
    # [[0, 1337566253.89858, 0.000355720520019531], 2]

#### 7.3.32.4.2.2. `min_border`

最小値を含めるかどうかを指定します。指定可能な値は次の通りです。

値 | 説明
--- | ---
`include` | `min` の値を含みます。これがデフォルト値です。
`exclude` | `min` の値を含みません。

次の例は `exclude` の使用例です。結果には `"Good-bye Senna"` レコードは含まれません。このレコードの `created_at` の値が `"2015/07/09 00:00:00"` だからです。

実行例:

    logical_count \
      --logical_table Entries \
      --shard_key created_at \
      --min "2015/07/09 00:00:00" \
      --min_border "exclude"
    # [[0, 1337566253.89858, 0.000355720520019531], 1]

#### 7.3.32.4.2.3. `max`

`shard_key` カラムの最大値を指定します。シャードにマッチするレコードがない場合、そのシャードは検索対象外になります。

たとえば、 `max` が `"2015/07/08 23:59:59"` なら `Entry_20150709` は検索対象外です。なぜなら `Entry_20150709` には `""2015/07/09"` のレコードしかないからです。

以下の例は `Entry_20150708` テーブルだけを使います。 `Entry_20150709` は使いません。

実行例:

    logical_count \
      --logical_table Entries \
      --shard_key created_at \
      --max "2015/07/08 23:59:59"
    # [[0, 1337566253.89858, 0.000355720520019531], 3]

#### 7.3.32.4.2.4. `max_border`

最大値を含めるかどうかを指定します。指定可能な値は次の通りです。

値 | 説明
--- | ---
`include` | `max` の値を含みます。これがデフォルト値です。
`exclude` | `max` の値を含みません。

次の例は `exclude` の使用例です。結果には `"Good-bye Senna"` レコードは含まれません。このレコードの `created_at` の値が `"2015/07/09 00:00:00"` だからです。

実行例:

    logical_count \
      --logical_table Entries \
      --shard_key created_at \
      --max "2015/07/09 00:00:00" \
      --max_border "exclude"
    # [[0, 1337566253.89858, 0.000355720520019531], 3]

### 7.3.32.4.3. 検索関係の引数

このコマンドは select 互換の検索関連パラメーターをサポートしています。

#### 7.3.32.4.3.1. `filter`

select の filter に対応しています。詳細は filter を見てください。

以下は例です。

実行例:

    logical_count \
      --logical_table Entries \
      --shard_key created_at \
      --filter "n_likes <= 5"
    # [[0, 1337566253.89858, 0.000355720520019531], 3]

#### 7.3.32.4.3.2. `post_filter`

バージョン 8.0.1 で追加.

`filtered` ステージの動的カラムが生成されてから実行するフィルターを指定します。 `post_filter` を使うと `filtered` ステージの動的カラムを使って絞り込むことができます。他は filter と同じです。

以下は人気のあるタグのエントリーだけを表示する例です。対象となるすべてのエントリーには `system` または `use` という単語が含まれています。

実行例:

    logical_count \
      --logical_table Entries \
      --shard_key created_at \
      --columns[n_likes_sum_per_tag].stage filtered \
      --columns[n_likes_sum_per_tag].type UInt32 \
      --columns[n_likes_sum_per_tag].value 'window_sum(n_likes)' \
      --columns[n_likes_sum_per_tag].window.group_keys 'tag' \
      --filter 'content @ "system" || content @ "use"' \
      --post_filter 'n_likes_sum_per_tag > 10' \
      --output_columns _key,n_likes,n_likes_sum_per_tag
    # [[0,1519095081.579662,0.4281206130981445],2]

### 7.3.32.4.4. 動的カラム関連の引数

バージョン 7.0.9 で追加.

select のすべての動的カラム関連パラメーターをサポートしています。詳細は 動的カラム関連の引数 を見てください。

#### 7.3.32.4.4.1. `columns[${NAME}].stage`

バージョン 7.0.9 で追加.

select の columns[${NAME}].stage に対応しています。詳細は columns[${NAME}].stage を見てください。

必須の引数です。

`initial` ステージと `filtered` ステージが有効です。なぜなら `output` ステージ以降にはなにも処理がないからです。

バージョン 8.0.1 で追加: `filtered` ステージは8.0.1から使えます。

以下は `initial` ステージで `is_popular` カラムを作る例です。作成した `is_popular` カラムは `filter` を含むすべてのパラメーターで使えます。

実行例:

    logical_count \
      --logical_table Entries \
      --shard_key created_at \
      --columns[is_popular].stage initial \
      --columns[is_popular].type Bool \
      --columns[is_popular].value 'n_likes >= 10' \
      --filter is_popular
    # [[0, 1337566253.89858, 0.000355720520019531], 2]

#### 7.3.32.4.4.2. `columns[${NAME}].flags`

バージョン 7.0.9 で追加.

select の columns[${NAME}].flags に対応しています。詳細は columns[${NAME}].flags を見てください。

デフォルト値は `COLUMN_SCALAR` です。

以下は `COLUMN_VECTOR` フラグを指定してベクターカラムを作る例です。 `plugin_register functions/vector` は vector_new 関数を使うために実行しています。:

実行例:

    plugin_register functions/vector
    # [[0, 1337566253.89858, 0.000355720520019531], true]
    logical_count \
      --logical_table Entries \
      --shard_key created_at \
      --columns[vector].stage initial \
      --columns[vector].flags COLUMN_VECTOR \
      --columns[vector].type UInt32 \
      --columns[vector].value 'vector_new(1, 2, 3)' \
      --filter 'vector_size(vector) > 2'
    # [[0, 1337566253.89858, 0.000355720520019531], 5]

#### 7.3.32.4.4.3. `columns[${NAME}].type`

バージョン 7.0.9 で追加.

select の columns[${NAME}].type に対応しています。詳細は columns[${NAME}].type を見てください。

必須の引数です。

以下は `ShortText` 型のカラムを作る例です。保存された値は自動的に `ShortText` にキャストされます。この例では数値が `ShortText` にキャストされています。

実行例:

    logical_count \
      --logical_table Entries \
      --shard_key created_at \
      --columns[n_likes_string].stage initial \
      --columns[n_likes_string].type ShortText \
      --columns[n_likes_string].value n_likes \
      --filter 'n_likes_string == "3"'
    # [[0, 1337566253.89858, 0.000355720520019531], 2]

#### 7.3.32.4.4.4. `columns[${NAME}].value`

バージョン 7.0.9 で追加.

select の columns[${NAME}].value に対応しています。詳細は columns[${NAME}].value を見てください。

ウィンドウ関数を使う場合は、 `value` の値に ウィンドウ関数 を指定し、さらに他のウィンドウ関数関連のパラメーターも指定する必要があります。詳細は ウィンドウ関数関連の引数 を見てください。

必須の引数です。

以下は内容の文字数を格納するための動的カラムを1つ作る例です。この例では文字数を数えるために `functions/string` プラグイン内の string_length 関数を使っています。 `functions/string` プラグインを登録するために plugin_register を使っています。

実行例:

    plugin_register functions/string
    # [[0, 1337566253.89858, 0.000355720520019531], true]
    logical_count \
      --logical_table Entries \
      --shard_key created_at \
      --columns[content_length].stage initial \
      --columns[content_length].type UInt32 \
      --columns[content_length].value 'string_length(content)' \
      --filter 'content_length >= 40'
    # [[0, 1337566253.89858, 0.000355720520019531], 2]

### 7.3.32.4.5. ウィンドウ関数関連の引数

バージョン 7.0.9 で追加.

select のすべてのウィンドウ関数関連パラメーターをサポートしています。詳細は ウィンドウ関数関連の引数 を見てください。

注釈

バージョン9.0.1以前では、複数のテーブルをまたがったウィンドウ関数はサポートしていません。バージョン9.0.2以降ではサポートしていますが、先頭のグループキーまたは、ソートキーがシャードキーと同じ順序で並んでいる必要があります。

例えば、以下のようなケースでは、複数のテーブルをまたいでウインドウ関数を適用できます。以下の例では、先頭のグループキーがシャードキーと同じ順序で並んでいるからです。

以下の例では、先頭のグループキーは `price` でシャードキーは `timestamp` です。 `price` と `timestamp` は同じ順序で並んでいるため、複数のテーブルをまたいでウインドウ関数を適用できます。

実行例:

    plugin_register sharding

    table_create Logs_20170415 TABLE_NO_KEY
    column_create Logs_20170415 timestamp COLUMN_SCALAR Time
    column_create Logs_20170415 price COLUMN_SCALAR UInt32
    column_create Logs_20170415 n_likes COLUMN_SCALAR UInt32

    table_create Logs_20170416 TABLE_NO_KEY
    column_create Logs_20170416 timestamp COLUMN_SCALAR Time
    column_create Logs_20170416 price COLUMN_SCALAR UInt32
    column_create Logs_20170416 n_likes COLUMN_SCALAR UInt32

    load --table Logs_20170415
    [
    {"timestamp": "2017/04/15 00:00:00", "n_likes": 2, "price": 100},
    {"timestamp": "2017/04/15 01:00:00", "n_likes": 1, "price": 100},
    {"timestamp": "2017/04/15 01:00:00", "n_likes": 2, "price": 200}
    ]

    load --table Logs_20170416
    [
    {"timestamp": "2017/04/16 10:00:00", "n_likes": 1, "price": 200},
    {"timestamp": "2017/04/16 11:00:00", "n_likes": 2, "price": 300},
    {"timestamp": "2017/04/16 11:00:00", "n_likes": 1, "price": 300}
    ]

    logical_count Logs \
      --shard_key timestamp \
      --columns[count].stage initial \
      --columns[count].type UInt32 \
      --columns[count].flags COLUMN_SCALAR \
      --columns[count].value 'window_count()' \
      --columns[count].window.group_keys price \
      --filter 'count >= 1'
    # [
    #   [
    #     0,
    #     0.0,
    #     0.0
    #   ],
    #   [
    #     4
    #   ]
    # ]

#### 7.3.32.4.5.1. `columns[${NAME}].window.sort_keys`

バージョン 7.0.9 で追加.

select の columns[${NAME}].window.sort_keys に対応しています。詳細は columns[${NAME}].window.sort_keys を見てください。

ウィンドウ関数を使うには columns[${NAME}].window.sort_keys または columns[${NAME}].window.group_keys を指定しなければいけません。

以下は `Entries.tag` 毎に累積和を計算する例です。各グループ内のレコードは `Entries._key` でソートします。

実行例:

    logical_count \
      --logical_table Entries \
      --shard_key created_at \
      --columns[n_likes_cumulative_sum_per_tag].stage initial \
      --columns[n_likes_cumulative_sum_per_tag].type UInt32 \
      --columns[n_likes_cumulative_sum_per_tag].value 'window_sum(n_likes)' \
      --columns[n_likes_cumulative_sum_per_tag].window.sort_keys _key \
      --columns[n_likes_cumulative_sum_per_tag].window.group_keys tag \
      --filter 'n_likes_cumulative_sum_per_tag > 5'
    # [[0, 1337566253.89858, 0.000355720520019531], 3]

#### 7.3.32.4.5.2. `columns[${NAME}].window.group_keys`

バージョン 7.0.9 で追加.

select の columns[${NAME}].window.group_keys に対応しています。詳細は columns[${NAME}].window.group_keys を見てください。

ウィンドウ関数を使うには columns[${NAME}].window.sort_keys または columns[${NAME}].window.group_keys を指定しなければいけません。

以下は `Entries.tag` 毎に合計を計算する例です。

実行例:

    logical_count \
      --logical_table Entries \
      --shard_key created_at \
      --columns[n_likes_sum_per_tag].stage initial \
      --columns[n_likes_sum_per_tag].type UInt32 \
      --columns[n_likes_sum_per_tag].value 'window_sum(n_likes)' \
      --columns[n_likes_sum_per_tag].window.group_keys tag \
      --filter 'n_likes_sum_per_tag > 5'
    # [[0, 1337566253.89858, 0.000355720520019531], 4]

### 7.3.32.4.6. キャッシュ関連の引数

#### 7.3.32.4.6.1. `cache`

このクエリーの結果をキャッシュするかどうかを指定します。

このクエリーの結果がキャッシュしてあると、次に同じクエリーを実行するときはキャッシュを使って高速にレスポンスを返すことができます。

これは既存のキャッシュされた結果を使うかどうかを指定するものではありません。

指定可能な値は以下の通りです。

値 | 説明
--- | ---
`no` | このクエリーの出力をキャッシュしない。
`yes` | このクエリーの出力をキャッシュする。デフォルト値。

このクエリーの結果をキャッシュしないようにする例です。

実行例:

    logical_count \
      --logical_table Entries \
      --shard_key created_at \
      --cache no
    # [[0, 1337566253.89858, 0.000355720520019531], 5]

デフォルト値は `yes` です。

## 7.3.32.5. 戻り値

このコマンドは以下のフォーマットのレスポンスを返します。:

    [HEADER, N_HITS]

このコマンドが失敗すると、 `HEADER` にエラーの詳細が含まれます。

`HEADER` については 出力形式 を参照してください。

`N_HITS` はマッチしたレコード数です。