お知らせ - 10系#

10.1.1リリース - 2021-01-25#

改良#

  • [select] Apache Arrow形式でUInt64の値の出力をサポートしました。

  • [select] Apache Arrow形式で以下のようにヒット数の出力をサポートしました。

    -- metadata --
    GROONGA:n-hits: 10
    
  • [query] "order by estimated size" の最適化をサポートしました。

    • 通常、ヒット数の少ない条件から最初に実行すると、高速に検索できます。

      • "A (ヒット数が多い) && B (ヒット数が少ない)" より "B (ヒット数が少ない) && A (ヒット数が多い)" 方が高速です。

    • これは、よく知られた最適化ですが、自分で条件を並び替える必要があります。

    • Groongaは、 "order by estimated size" の最適化を使うことで、自動的にこの並び替えを実行します。

    • この最適化は、 GRN_ORDER_BY_ESTIMATED_SIZE_ENABLE=yes で有効になります。

  • [between] 以下の改良で、パフォーマンスを改善しました。

    • between() でシーケンシャルサーチを使うかどうかの判断の精度を改善しました。

    • between() の結果を結果セットに一度にセットするよう改善しました。

  • [select] 前方一致検索のパフォーマンスを改善しました。

    • 例えば、以下のような "*" を使った前方一致検索のパフォーマンスが向上します。

      table_create Memos TABLE_PAT_KEY ShortText
      table_create Contents TABLE_PAT_KEY ShortText   --normalizer NormalizerAuto
      column_create Contents entries_key_index COLUMN_INDEX Memos _key
      
      load --table Memos
      [
      {"_key": "(groonga) Start to try!"},
      {"_key": "(mroonga) Installed"},
      {"_key": "(groonga) Upgraded!"}
      ]
      
      select \
        --table Memos \
        --match_columns _key \
        --query '\\(groonga\\)*'
      
  • [トークナイザー][TokenMecab] トークンカラムを並列で構築する際のパフォーマンスを改善しました。 [GitHub#1158][naoaさんがパッチ提供]

修正#

  • [sub_filter] slices[].filter 内で sub_filter が動作しない問題を修正しました。

    • 例えば、以下のクエリーでは、この問題によって、 sub_filter の結果は0件になります。

      table_create Users TABLE_HASH_KEY ShortText
      column_create Users age COLUMN_SCALAR UInt8
      
      table_create Memos TABLE_NO_KEY
      column_create Memos user COLUMN_SCALAR Users
      column_create Memos content COLUMN_SCALAR Text
      
      load --table Users
      [
      {"_key": "alice", "age": 9},
      {"_key": "bob",   "age": 29}
      ]
      
      load --table Memos
      [
      {"user": "alice", "content": "hello"},
      {"user": "bob",   "content": "world"},
      {"user": "alice", "content": "bye"},
      {"user": "bob",   "content": "yay"}
      ]
      
      select \
        --table Memos \
        --slices[adult].filter '_id > 1 && sub_filter(user, "age >= 18")'
      
  • ハッシュテーブルに対して、繰り返し大量のデータを追加、削除すると、Groongaがクラッシュしたり、データの追加ができなくなる可能性がある問題を修正しました。

感謝#

  • naoaさん

10.1.0リリース - 2020-12-29#

改良#

  • [highlight_html] 全角スペースをハイライト対処から除外しました。[PGroonga#GitHub#155][Hung Nguyen Vさんが報告]

    • 今までは、以下のように先頭の全角スペースも含めてハイライト対象としていました。

      table_create Entries TABLE_NO_KEY
      column_create Entries body COLUMN_SCALAR ShortText
      
      table_create Terms TABLE_PAT_KEY ShortText --default_tokenizer TokenBigram --normalizer NormalizerAuto
      column_create Terms document_index COLUMN_INDEX|WITH_POSITION Entries body
      
      load --table Entries
      [
      {"body": "Groonga 高速!"}
      ]
      
      select Entries --output_columns \
        --match_columns body --query '高速' \
        --output_columns 'highlight_html(body)'
      [
        [
          0,
          0.0,
          0.0
        ],
        [
          [
            [
              1
            ],
            [
              [
                "highlight_html",
                null
              ]
            ],
            [
              "Groonga<span class=\"keyword\"> 高速</span>!"
            ]
          ]
        ]
      ]
      
    • しかし、この全角スペースはハイライト対象としては不要です。そのため、このリリースから highlight_html() は先頭の全角スペースを削除します。

  • [status] 新しい項目 features を追加しました。

    • 以下のように、Groongaのどの機能が有効なのかを表示できます。

      status --output_pretty yes
      [
        [
          0,
          0.0,
          0.0
        ],
        {
          "alloc_count": 361,
          "starttime": 1608087311,
          "start_time": 1608087311,
          "uptime": 35,
          "version": "10.1.0",
          "n_queries": 0,
          "cache_hit_rate": 0.0,
          "command_version": 1,
          "default_command_version": 1,
          "max_command_version": 3,
          "n_jobs": 0,
          "features": {
            "nfkc": true,
            "mecab": true,
            "message_pack": true,
            "mruby": true,
            "onigmo": true,
            "zlib": true,
            "lz4": false,
            "zstandard": false,
            "kqueue": false,
            "epoll": true,
            "poll": false,
            "rapidjson": false,
            "apache_arrow": false,
            "xxhash": false
          }
        }
      ]
      
  • [status] 新しい項目 apache_arrow を追加しました。

    • 以下のようにGroongaが使うApache Arrowのバージョンを表示できます。

    [
      [
        0,
        1608088628.440753,
        0.0006628036499023438
      ],
      {
        "alloc_count": 360,
        "starttime": 1608088617,
        "start_time": 1608088617,
        "uptime": 11,
        "version": "10.0.9-39-g5a4c6f3",
        "n_queries": 0,
        "cache_hit_rate": 0.0,
        "command_version": 1,
        "default_command_version": 1,
        "max_command_version": 3,
        "n_jobs": 0,
        "features": {
          "nfkc": true,
          "mecab": true,
          "message_pack": true,
          "mruby": true,
          "onigmo": true,
          "zlib": true,
          "lz4": true,
          "zstandard": false,
          "kqueue": false,
          "epoll": true,
          "poll": false,
          "rapidjson": false,
          "apache_arrow": true,
          "xxhash": false
        },
        "apache_arrow": {
          "version_major": 2,
          "version_minor": 0,
          "version_patch": 0,
          "version": "2.0.0"
        }
      }
    ]
    
    • この項目は、Apache Arrowが有効な場合にのみ表示されます。

  • [ウィンドウ関数] 対象のテーブルがシャードをまたいでいる場合でも、全てのテーブルを一度に処理するようにしました。(実験的)

    • 今まで、対象のテーブルがシャードをまたいでいた場合、ウインドウ関数はシャード毎に処理をしていました。

      • そのため、複数のグループキーを使う場合、2番目以降のグループキーの値は1種類でなければなりませんでした。

      • この改良によって、以下のように複数の種類の値を2番目以降のグループキーで使用できるようになります。

        plugin_register sharding
        plugin_register functions/time
        
        table_create Logs_20170315 TABLE_NO_KEY
        column_create Logs_20170315 timestamp COLUMN_SCALAR Time
        column_create Logs_20170315 price COLUMN_SCALAR UInt32
        column_create Logs_20170315 item COLUMN_SCALAR ShortText
        
        table_create Logs_20170316 TABLE_NO_KEY
        column_create Logs_20170316 timestamp COLUMN_SCALAR Time
        column_create Logs_20170316 price COLUMN_SCALAR UInt32
        column_create Logs_20170316 item COLUMN_SCALAR ShortText
        
        table_create Logs_20170317 TABLE_NO_KEY
        column_create Logs_20170317 timestamp COLUMN_SCALAR Time
        column_create Logs_20170317 price COLUMN_SCALAR UInt32
        column_create Logs_20170317 item COLUMN_SCALAR ShortText
        
        load --table Logs_20170315
        [
        {"timestamp": "2017/03/15 10:00:00", "price": 1000, "item": "A"},
        {"timestamp": "2017/03/15 11:00:00", "price":  900, "item": "A"},
        {"timestamp": "2017/03/15 12:00:00", "price":  300, "item": "B"},
        {"timestamp": "2017/03/15 13:00:00", "price":  200, "item": "B"}
        ]
        
        load --table Logs_20170316
        [
        {"timestamp": "2017/03/16 10:00:00", "price":  530, "item": "A"},
        {"timestamp": "2017/03/16 11:00:00", "price":  520, "item": "B"},
        {"timestamp": "2017/03/16 12:00:00", "price":  110, "item": "A"},
        {"timestamp": "2017/03/16 13:00:00", "price":  410, "item": "A"},
        {"timestamp": "2017/03/16 14:00:00", "price":  710, "item": "B"}
        ]
        
        load --table Logs_20170317
        [
        {"timestamp": "2017/03/17 10:00:00", "price":  800, "item": "A"},
        {"timestamp": "2017/03/17 11:00:00", "price":  400, "item": "B"},
        {"timestamp": "2017/03/17 12:00:00", "price":  500, "item": "B"},
        {"timestamp": "2017/03/17 13:00:00", "price":  300, "item": "A"}
        ]
        
        table_create Times TABLE_PAT_KEY Time
        column_create Times logs_20170315 COLUMN_INDEX Logs_20170315 timestamp
        column_create Times logs_20170316 COLUMN_INDEX Logs_20170316 timestamp
        column_create Times logs_20170317 COLUMN_INDEX Logs_20170317 timestamp
        
        logical_range_filter Logs \
          --shard_key timestamp \
          --filter 'price >= 300' \
          --limit -1 \
          --columns[offsetted_timestamp].stage filtered \
          --columns[offsetted_timestamp].type Time \
          --columns[offsetted_timestamp].flags COLUMN_SCALAR \
          --columns[offsetted_timestamp].value 'timestamp - 39600000000' \
          --columns[offsetted_day].stage filtered \
          --columns[offsetted_day].type Time \
          --columns[offsetted_day].flags COLUMN_SCALAR \
          --columns[offsetted_day].value 'time_classify_day(offsetted_timestamp)' \
          --columns[n_records_per_day_and_item].stage filtered \
          --columns[n_records_per_day_and_item].type UInt32 \
          --columns[n_records_per_day_and_item].flags COLUMN_SCALAR \
          --columns[n_records_per_day_and_item].value 'window_count()' \
          --columns[n_records_per_day_and_item].window.group_keys 'offsetted_day,item' \
          --output_columns "_id,time_format_iso8601(offsetted_day),item,n_records_per_day_and_item"
        [
          [
            0,
            0.0,
            0.0
          ],
          [
            [
              [
                "_id",
                "UInt32"
              ],
              [
                "time_format_iso8601",
                null
              ],
              [
                "item",
                "ShortText"
              ],
              [
                "n_records_per_day_and_item",
                "UInt32"
              ]
            ],
            [
              1,
              "2017-03-14T00:00:00.000000+09:00",
              "A",
              1
            ],
            [
              2,
              "2017-03-15T00:00:00.000000+09:00",
              "A",
              2
            ],
            [
              3,
              "2017-03-15T00:00:00.000000+09:00",
              "B",
              1
            ],
            [
              1,
              "2017-03-15T00:00:00.000000+09:00",
              "A",
              2
            ],
            [
              2,
              "2017-03-16T00:00:00.000000+09:00",
              "B",
              2
            ],
            [
              4,
              "2017-03-16T00:00:00.000000+09:00",
              "A",
              2
            ],
            [
              5,
              "2017-03-16T00:00:00.000000+09:00",
              "B",
              2
            ],
            [
              1,
              "2017-03-16T00:00:00.000000+09:00",
              "A",
              2
            ],
            [
              2,
              "2017-03-17T00:00:00.000000+09:00",
              "B",
              2
            ],
            [
              3,
              "2017-03-17T00:00:00.000000+09:00",
              "B",
              2
            ],
            [
              4,
              "2017-03-17T00:00:00.000000+09:00",
              "A",
              1
            ]
          ]
        ]
        
    • この機能には、まだリリースされていない、Apache Arrow 3.0.0が必要です。

  • 参照カラムに対する検索でシーケンシャルサーチをサポートしました。

    • この機能は、インデックス検索でたくさんのレコードがマッチした場合、かつ結果セットが十分小さい場合にのみ使われます。

      • 上記のケースでは、インデックス検索よりもシーケンシャルサーチの方が速いためです。

    • この機能はデフォルトでは無効です。

    • この機能は、環境変数 GRN_II_SELECT_TOO_MANY_INDEX_MATCH_RATIO_REFERENCE を設定することで有効になります。

    • 環境変数 GRN_II_SELECT_TOO_MANY_INDEX_MATCH_RATIO_REFERENCE はインデックス検索からシーケンシャルサーチに切り替えるためのしきい値です。

      • 例えば、以下のように GRN_II_SELECT_TOO_MANY_INDEX_MATCH_RATIO_REFERENCE=0.7 とセットした場合、結果セットのレコード数が、総レコード数の70%以下の場合にシーケンシャルサーチで検索します。

        $ export GRN_II_SELECT_TOO_MANY_INDEX_MATCH_RATIO_REFERENCE=0.7
        
        table_create Tags TABLE_HASH_KEY ShortText
        table_create Memos TABLE_HASH_KEY ShortText
        column_create Memos tag COLUMN_SCALAR Tags
        
        load --table Memos
        [
        {"_key": "Rroonga is fast!", "tag": "Rroonga"},
        {"_key": "Groonga is fast!", "tag": "Groonga"},
        {"_key": "Mroonga is fast!", "tag": "Mroonga"},
        {"_key": "Groonga sticker!", "tag": "Groonga"},
        {"_key": "Groonga is good!", "tag": "Groonga"}
        ]
        
        column_create Tags memos_tag COLUMN_INDEX Memos tag
        
        select Memos --query '_id:>=3 tag:@Groonga' --output_columns _id,_score,_key,tag
        [
          [
            0,
            0.0,
            0.0
          ],
          [
            [
              [
                2
              ],
              [
                [
                  "_id",
                  "UInt32"
                ],
                [
                  "_score",
                  "Int32"
                ],
                [
                  "_key",
                  "ShortText"
                ],
                [
                  "tag",
                  "Tags"
                ]
              ],
              [
                4,
                2,
                "Groonga sticker!",
                "Groonga"
              ],
              [
                5,
                2,
                "Groonga is good!",
                "Groonga"
              ]
            ]
          ]
        ]
        
  • [tokenizers] TokenDocumentVectorTFIDFTokenDocumentVectorBM25 でトークンカラムをサポートしました。

    • インデックスカラムと同じソースを持つトークンカラムがある場合、これらのトークナイザーは、トークンカラムのトークンIDを使います。

      • トークンカラムは、既にトークナイズ済みのデータを持っています。

      • そのため、トークンカラムを使うことによって、これらのトークナイザーのパフォーマンスが改善されます。

    • 例えば、以下のように、 content_tokens というトークンカラムを作ることで、この機能を使えます。

      table_create Memos TABLE_NO_KEY
      column_create Memos content COLUMN_SCALAR Text
      
      load --table Memos
      [
      {"content": "a b c a"},
      {"content": "c b c"},
      {"content": "b b a"},
      {"content": "a c c"},
      {"content": "a"}
      ]
      
      table_create Tokens TABLE_PAT_KEY ShortText \
        --normalizer NormalizerNFKC121 \
        --default_tokenizer TokenNgram
      column_create Tokens memos_content COLUMN_INDEX|WITH_POSITION Memos content
      
      column_create Memos content_tokens COLUMN_VECTOR Tokens content
      
      table_create DocumentVectorBM25 TABLE_HASH_KEY Tokens \
        --default_tokenizer \
          'TokenDocumentVectorBM25("index_column", "memos_content", \
                                   "df_column", "df")'
      column_create DocumentVectorBM25 df COLUMN_SCALAR UInt32
      
      column_create Memos content_feature COLUMN_VECTOR|WITH_WEIGHT|WEIGHT_FLOAT32 \
        DocumentVectorBM25 content
      
      select Memos
      [
        [
          0,
          0.0,
          0.0
        ],
        [
          [
            [
              5
            ],
            [
              [
                "_id",
                "UInt32"
              ],
              [
                "content",
                "Text"
              ],
              [
                "content_feature",
                "DocumentVectorBM25"
              ],
              [
                "content_tokens",
                "Tokens"
              ]
            ],
            [
              1,
              "a b c a",
              {
                "a": 0.5095787,
                "b": 0.6084117,
                "c": 0.6084117
              },
              [
                "a",
                "b",
                "c",
                "a"
              ]
            ],
            [
              2,
              "c b c",
              {
                "c": 0.8342565,
                "b": 0.5513765
              },
              [
                "c",
                "b",
                "c"
              ]
            ],
            [
              3,
              "b b a",
              {
                "b": 0.9430448,
                "a": 0.3326656
              },
              [
                "b",
                "b",
                "a"
              ]
            ],
            [
              4,
              "a c c",
              {
                "a": 0.3326656,
                "c": 0.9430448
              },
              [
                "a",
                "c",
                "c"
              ]
            ],
            [
              5,
              "a",
              {
                "a": 1.0
              },
              [
                "a"
              ]
            ]
          ]
        ]
      ]
      
    • TokenDocumentVectorTFIDFTokenDocumentVectorBM25 は、各トークンに対して重みをつけます。

  • 以下のケースのパフォーマンスを改善しました。

    • (column @ "value") && (column @ "value")

  • [Ubuntu] Ubuntu 20.10 (Groovy Gorilla)をサポートしました。

  • [Debian GNU/Linux] stretchのサポートをやめました。

    • EOLになったためです。

  • [CentOS] CentOS 6のサポートをやめました。

    • EOLになったためです。

  • [httpd] バンドルしているnginxのバージョンを1.19.6に更新しました。

修正#

  • 以下のように、複数のドリルダウンのキーと複数のアクセサーを使用した時にGroongaがクラッシュする問題を修正しました。[GitHub#1153][naoaさんがパッチ提供]

    table_create Tags TABLE_PAT_KEY ShortText
    
    table_create Memos TABLE_HASH_KEY ShortText
    column_create Memos tags COLUMN_VECTOR Tags
    column_create Memos year COLUMN_SCALAR Int32
    
    load --table Memos
    [
    {"_key": "Groonga is fast!", "tags": ["full-text-search"], "year": 2019},
    {"_key": "Mroonga is fast!", "tags": ["mysql", "full-text-search"], "year": 2019},
    {"_key": "Groonga sticker!", "tags": ["full-text-search", "sticker"], "year": 2020},
    {"_key": "Rroonga is fast!", "tags": ["full-text-search", "ruby"], "year": 2020},
    {"_key": "Groonga is good!", "tags": ["full-text-search"], "year": 2020}
    ]
    
    select Memos \
      --filter '_id > 0' \
      --drilldowns[tags].keys 'tags,year >= 2020' \
      --drilldowns[tags].output_columns _key[0],_key[1],_nsubrecs
    
    select Memos \
      --filter '_id > 0' \
      --drilldowns[tags].keys 'tags,year >= 2020' \
      --drilldowns[tags].output_columns _key[1],_nsubrecs
    
  • 以下のように、同じフレーズが複数回出現すると、近傍フレーズ検索がマッチしない問題を修正しました。

    table_create Entries TABLE_NO_KEY
    column_create Entries content COLUMN_SCALAR Text
    
    table_create Terms TABLE_PAT_KEY ShortText \
      --default_tokenizer TokenNgram \
      --normalizer NormalizerNFKC121
    column_create Terms entries_content COLUMN_INDEX|WITH_POSITION Entries content
    
    load --table Entries
    [
    {"content": "a x a x b x x"},
    {"content": "a x x b x"}
    ]
    
    select Entries \
      --match_columns content \
      --query '*NP2"a b"' \
      --output_columns '_score, content'
    

感謝#

  • Hung Nguyen Vさん

  • naoaさん

  • timgates42さん [GitHub#1155にてパッチ提供]

10.0.9リリース - 2020-12-01#

改良#

  • limit-1 を指定した時のパフォーマンスを改善しました。

  • [reference_acquire] 新しいオプション --auto_release_count を追加しました。

    • Groongaは、リクエストが --auto_release_count で指定された値に到達した時に自動的に参照カウントを減らします。

    • 例えば、以下のように、取得した User の参照は、2番目の status が処理された後に自動的に解放されます。

      reference_acquire --target_name Users --auto_release_count 2
      status # Users is still referred.
      status # Users' reference is released after this command is processed.
      
    • このオプションで、取得した参照の解放漏れを防げます。

  • Groongaが空の vectoruvector を評価した時の動作を変更しました。

    • 空の vectoruvector はcommand version 3では、 false と評価されます。

      • この挙動はcommand version 3でのみ有効です。

      • 今までとは挙動が異なることに注意してください。

  • [ノーマライザー] Unicode 13.0 の NFKC(Normalization Form Compatibility Composition)をベースにしたノーマライザー NormalizerNFKC130 を追加しました。

  • [トークンフィルター] Unicode 13.0 の NFKC(Normalization Form Compatibility Composition)をベースにしたトークンフィルター TokenFilterNFKC130 を追加しました。

  • [select] "_score = column - X" のパフォーマンスを改善しました。

  • [reference_acquire] --recursive dependent オプションを指定した時に必要のないインデックスカラムへの参照を取得しないように改善しました。

    • 今回のリリースから、 --recursive dependent の対象は、対象のテーブルのキーあるいはデータカラムに設定してあるインデックスカラムです。

  • [select] 順序限定の近傍フレーズ検索をサポートしました。

    • 今までの近傍フレーズ検索は、指定したフレーズ間の距離が近いレコードのみを探していました。

    • この機能は、以下の条件を満たすレコードを探します。

      • 指定したフレーズ間の距離が近い場合。

      • 指定したフレーズが指定した順序で並んでいる場合。

    • この機能は、 *ONP を演算子として使います。(*NP 演算子ではないことに注意してください。)

    • $ はクエリー構文では、 $ そのものとして扱います。クエリー構文では、 $ は特殊文字ではないことに注意してください。

    • スクリプト構文の場合、この機能は以下のように使用します。

      table_create Entries TABLE_NO_KEY
      column_create Entries content COLUMN_SCALAR Text
      
      table_create Terms TABLE_PAT_KEY ShortText \
        --default_tokenizer 'TokenNgram("unify_alphabet", false, \
                                        "unify_digit", false)' \
        --normalizer NormalizerNFKC121
      column_create Terms entries_content COLUMN_INDEX|WITH_POSITION Entries content
      
      load --table Entries
      [
      {"content": "abcXYZdef"},
      {"content": "abebcdXYZdef"},
      {"content": "abcdef"},
      {"content": "defXYZabc"},
      {"content": "XYZabc"},
      {"content": "abc123456789def"},
      {"content": "abc12345678def"},
      {"content": "abc1de2def"}
      ]
      
      select Entries --filter 'content *ONP "abc def"' --output_columns '_score, content'
      [
        [
          0,
          0.0,
          0.0
        ],
        [
          [
            [
              4
            ],
            [
              [
                "_score",
                "Int32"
              ],
              [
                "content",
                "Text"
              ]
            ],
            [
              1,
              "abcXYZdef"
            ],
            [
              1,
              "abcdef"
            ],
            [
              1,
              "abc12345678def"
            ],
            [
              1,
              "abc1de2def"
            ]
          ]
        ]
      ]
      
    • クエリー構文の場合、この機能は以下のように使用します。

      select Entries --query 'content:*ONP "abc def"' --output_columns '_score, content'
      [
        [
          0,
          0.0,
          0.0
        ],
        [
          [
            [
              4
            ],
            [
              [
                "_score",
                "Int32"
              ],
              [
                "content",
                "Text"
              ]
            ],
            [
              1,
              "abcXYZdef"
            ],
            [
              1,
              "abcdef"
            ],
            [
              1,
              "abc12345678def"
            ],
            [
              1,
              "abc1de2def"
            ]
          ]
        ]
      ]
      
  • [httpd] バンドルしているnginxのバージョンを1.19.5に更新しました。

修正#

  • [Groonga HTTPサーバー] Groonga HTTP server が全てのワーカースレッドの完全な終了を待たずに終了していた問題を修正しました。

    • 今まで、Groonga HTTP server は、ワーカースレッドの処理が終了した後から、自身の終了処理を開始していました。しかし、このタイミングでは、ワーカースレッドは完全に終了していないことがあります。そのため、タイミングによってはGroonga HTTP serverがクラッシュすることがあります。Groonga HTTP server がワーカースレッドがまだ使用している領域を解放することがあるためです。

10.0.8リリース - 2020-10-29#

改良#

  • [select] 大きいサイズのドリルダウンのキーを使えるようになりました。

    • Groongaのテーブルのキーサイズの最大は4KiBですが、複数のドリルダウンのキーを指定している場合、ドリルダウンのキーのサイズが4KiBを超える場合があります。

      • 例えば、以下のケースで、 tag キーと n_like キーのトータルサイズが4KiB以上だった場合、ドリルダウンは失敗します。

      select Entries \
        --limit -1 \
        --output_columns tag,n_likes \
        --drilldowns[tag.n_likes].keys tag,n_likes \
        --drilldowns[tag.n_likes].output_columns _value.tag,_value.n_likes,_nsubrecs
      
      • ドリルダウンは指定されている全てのキーを連結しているためです。そのため、ドリルダウンのキーそれぞれが大きい場合は、ドリルダウンのキーを連結したサイズが4KiB以上になります。

    • この機能には、 xxHash が必要です。

      • ただ、Groongaをパッケージからインストールしている場合は、特に何もしなくてもこの機能を使えます。Groongaのパッケージには、すでに xxHash が含まれているためです。

  • [select] 異なるテーブルを参照しているカラムを同じ動的カラムで扱えるようにしました。

    • 従来、異なるテーブルを参照しているカラムは、同一の動的カラムでは扱えませんでした。カラムの型が異なるためです。

    • 今回のバージョンから、以下のように異なるテーブルを参照しているカラムであってもビルトインの型にキャストすることで同じ動的カラムで扱うことができます。

      table_create Store_A TABLE_HASH_KEY ShortText
      table_create Store_B TABLE_HASH_KEY ShortText
      
      table_create Customers TABLE_HASH_KEY Int32
      column_create Customers customers_A COLUMN_VECTOR Store_A
      column_create Customers customers_B COLUMN_VECTOR Store_B
      
      load --table Customers
      [
        {"_key": 1604020694, "customers_A": ["A", "B", "C"]},
        {"_key": 1602724694, "customers_B": ["Z", "V", "Y", "T"]},
      ]
      
      select Customers \
        --filter '_key == 1604020694' \
        --columns[customers].stage output \
        --columns[customers].flags COLUMN_VECTOR \
        --columns[customers].type ShortText \
        --columns[customers].value 'customers_A' \
        --output_columns '_key, customers'
      
    • 今までは、 Store_A または Store_Bcustomers カラムの type に設定する必要がありました。

    • 上記の例では、 customers_A カラムの型は、 ShortText にキャストします。

    • customers_A のキーも customers_B のキーも ShortText 型であるため、これで customers カラムの値に customers_B の値も設定できます。

  • [select] 検索結果のレコード数が非常に多い場合のパフォーマンスを改善しました。

    • この最適化は、以下のケースで効果があります。

      • --filter 'column <= "value"' or --filter 'column >= "value"'

      • --filter 'column == "value"'

      • --filter 'between(...)' または --filter 'between(_key, ...)'

      • --filter 'sub_filter(reference_column, ...)'

      • --filter '_key > "value"' のような _key に対する比較

      • --filter 'geo_in_circle(...)'

  • バンドルしているLZ4を1.8.2から1.9.2に更新しました。

  • xxHash 0.8 をサポートしました。

  • [httpd] バンドルしているnginxのバージョンを1.19.4に更新しました。

修正#

  • ブラウザーベースの管理ツール関連の問題を修正しました。 [GitHub#1139][sutaminさんの報告]

    • Groongaのロゴが表示されない問題。

    • 日本語のインデックスページにスループットグラフが表示されない問題。

  • [between] between(_key, ...) が常にシーケンシャルサーチで評価される問題を修正しました。

感謝#

  • sutaminさん

10.0.7リリース - 2020-09-29#

改良#

  • [highlight], [highlight_full] ノーマライザーにオプションを指定できるようになりました。

  • [リターンコード] 新しいリターンコード GRN_CONNECTION_RESET を追加しました。

    • このリターンコードは、リモートホストから強制的に接続を切断されたときに返されます。

  • Ubuntu 19.10(Eoan Ermine)のサポートをやめました。

    • このバージョンはEOLになっているためです。

  • [httpd] バンドルしているnginxのバージョンを1.19.2に更新しました。

  • [grndb] キーの重複を検出できるようになりました。

    • 今回のリリースから、 grndb check でキーの重複も検出できるようになりました。

    • このチェックは、 TABLE_NO_KEY のテーブル以外で有効です。

    • grndb check で重複が検出されたテーブルにインデックスカラムしかない場合は、 grndb recover で復旧できます。

  • [table_create], [column_create] 新しいオプション --path を追加しました。

    • このオプションによって指定したテーブルまたは、カラムを任意のパスに格納できます。

    • このオプションは、高速なストレージ(SSDなど)によく使うテーブルやカラムを格納し、低速なストレージ(HDDなど)にあまり使わないテーブルやカラムを格納したいときに有用です。

    • このオプションは、相対パス、絶対パスの両方が指定できます。

      • 相対パスを指定した場合は、 groonga プロセスのパスを起点に指定したパスが解決されます。

    • --path を指定した場合、 dump コマンドの結果に --path の情報が含まれます。

      • したがって、 --path を指定した場合、 異なる環境のホストではリストアできなくなります。

        • これは、ディレクトリ構成や groonga プロセスの場所が環境ごとに異なるためです。

      • --path の情報を dump に含みたくない場合は、 dump コマンド実行時に --dump_paths no を指定する必要があります。

  • [dump] 新しいオプション --dump_paths を追加しました。

    • --dump_paths オプションは、 --path をダンプするかどうかを制御します。

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

    • もし、テーブルやカラム作成時に --path を指定していて、 --path の情報を dump に含みたくない場合は、 dump コマンド実行時に --dump_pathsno を指定してください。

  • 新しい関数 string_toknize() を追加しました。

    • この関数は、第二引数に指定されたカラムの値を、第一引数に指定されたトークナイザーでトークナイズします。

  • [tokenizers] 新しいトークナイザー TokenDocumentVectorTFIDF を追加しました。(実験的)

    • このトークナイザーは、TF-IDFで文書ベクトルを自動で生成します。

  • [tokenizers] 新しいトークナイザー TokenDocumentVectorBM25 を追加しました。(実験的)

    • このトークナイザーは、BM25で文書ベクトルを自動で生成します。

  • [select] 同一センテンス内での、フレーズ近傍検索をサポートしました。

修正#

  • [load] 257個のカラムに対して load を実行すると load の応答が返らなくなる問題を修正しました。

    • この問題は、10.0.4以降で発生する可能性があります。

    • この問題は、 [a, b, c, ...] の形式でデータをロードした時にのみ発生します。

      • [{...}] を使ってデータをロードした場合は発生しません。

  • [MessagePack] float32の値を正しくアンパックできない問題を修正しました。

  • マルチカラムインデックス関連の問題を修正しました。

10.0.6リリース - 2020-08-29#

改良#

  • [logical_range_filter] 大きなデータの検索プランを改善しました。

    • 通常、 logical_range_filterlogical_select より高速ですが、以下のケースでは、 logical_select より遅くなっていました。

      • logical_range_filter には要求されたレコード数をなかなか見つけられない場合にシーケンシャル検索からインデックス検索に切り替える機能があります。( logical_range_filter は通常、検索対象のレコード数が多い場合は、シーケンシャル検索を使います。)

      • 上記の切り替えが発生した場合は、 logical_select と検索処理がほぼ同じになります。そのため、大きなデータを対象とした検索では、上記のケースで、 logical_range_filter は、 logical_select の数倍遅くなります。なぜなら、 logical_range_filter は検索後にソートを実行するためです。

    • 今回のリリースから、大きなデータを検索する場合に、今までよりシーケンシャル検索が採用されやすくしました。

    • これによって、 logical_select と同等の処理になるケースが減少し logical_range_filter のパフォーマンスが改善します。

  • [httpd] バンドルしているnginxのバージョンを1.19.1に更新しました。

  • Debian GNU/Linux へのインストール方法を変更しました。

    • groonga-archive-keyring の代わりに groonga-apt-source を使うように変更しました。 lintian コマンドが /etc/apt/sources.lists.d/ 配下にファイルを置くパッケージは apt-source を使うよう推奨しているためです。

      • lintian コマンドはパッケージングに共通のエラーをチェックするためのコマンドです。

      • インストール方法についての詳細は、以下のURLも参照してください。

  • [logical_select] highlight_htmlhighlight_full をサポートしました。

  • 値を持たない配列を削除した時、そのレコードのIDを再利用するようにしました。[GitHub#mroonga/mroonga#327][gaeeyoさんの報告]

    • 値を持たない配列を削除した場合、削除されたIDは再利用されません。

    • Groongaは大きなIDがあることによって、多くのストレージを使用します。大きなIDはそれだけで、多くのストレージを使うためです。

      • 大きなIDは、例えば、Mroongaの mroonga_operations のように多くの追加と削除によって発生します。

  • [select] インデックスを設定していない全文検索のパフォーマンスを改善しました。

  • [関数] 全ての引数が他のテーブルへの参照か、リテラルである関数のパフォーマンスを改善しました。

  • [インデックス構築] トークンカラムを使った静的インデックス構築のパフォーマンスを改善しました。 [GitHub#1126][naoaさんがパッチ提供]

  • "_score = func(...)" のパフォーマンスを改善しました。

    • _score の値が "_score = func(...)" のように関数によってのみ算出される場合のパフォーマンスを改善しました。

修正#

  • 応答送信のエラーが発生した後の応答にゴミが含まれることがある問題を修正しました。

    • これは、クライアントが全ての応答を読み込まずにコネクションがクローズされた場合に発生することがあります。

感謝#

  • gaeeyoさん

  • naoaさん

10.0.5リリース - 2020-07-30#

改良#

  • [select] -load_table で指定したテーブルに参照を格納できるようにしました。

    • --load-table は予め用意したテーブルに検索結果を格納する機能です。

      • 複数回検索が実行される場合、このテーブルに結果を格納することで、検索結果をキャッシュできます。

      • このテーブルを使うことで、初回以降の検索時間を短縮できます。

    • 今回のリリース以降で、以下のようにこのテーブルに別のテーブルへの参照を格納できます。

      • カラムの値を格納せず、参照のみを格納するため、このテーブルのサイズを小さくすることができます。

      • このテーブルに対して検索する場合、参照先のテーブルのインデックスを使って検索できます。

      table_create Logs TABLE_HASH_KEY ShortText
      column_create Logs timestamp COLUMN_SCALAR Time
      
      table_create Times TABLE_PAT_KEY Time
      column_create Times logs_timestamp COLUMN_INDEX Logs timestamp
      
      table_create LoadedLogs TABLE_HASH_KEY Logs
      
      load --table Logs
      [
      {
        "_key": "2015-02-03:1",
        "timestamp": "2015-02-03 10:49:00"
      },
      {
        "_key": "2015-02-03:2",
        "timestamp": "2015-02-03 12:49:00"
      },
      {
        "_key": "2015-02-04:1",
        "timestamp": "2015-02-04 00:00:00"
      }
      ]
      
      select \
        Logs \
        --load_table LoadedLogs \
        --load_columns "_key" \
        --load_values "_key" \
        --limit 0
      
      select \
        --table LoadedLogs \
        --filter 'timestamp >= "2015-02-03 12:49:00"'
      [
        [
          0,
          0.0,
          0.0
        ],
        [
          [
            [
              2
            ],
            [
              [
                "_id",
                "UInt32"
              ],
              [
                "_key",
                "ShortText"
              ],
              [
                "timestamp",
                "Time"
              ]
            ],
            [
              2,
              "2015-02-03:2",
              1422935340.0
            ],
            [
              3,
              "2015-02-04:1",
              1422975600.0
            ]
          ]
        ]
      ]
      
  • [select] 以下のケースのソートのパフォーマンスを改善しました。

    • 多くのソートキーがID解決をする場合。

      • 例えば、以下の式はIDを解決する必要があります。

        • --filter true --sort_keys column

      • 例えば、以下の式はIDを解決する必要がありません。 擬似カラム _score は、結果テーブルに存在しており、ソーステーブルには存在しないためIDを解決する必要がありません。

        • --filter true --sort_keys _score

    • ソート対象のテーブルがキーを持っている場合。

      • したがって、 TABLE_NO_KEY はこの改善をサポートしていません。

  • [select] 以下のケースのパフォーマンスを少し改善しました。

    • 沢山のレコードがマッチする検索をしているケース。

    • 沢山のレコードに対してドリルダウンするケース。

  • [aggregator] score アクセサーをサポートしました。[GitHub#1120][naoaさんのパッチ提供]

    • 例えば、 以下のように _scoreaggregator_* の対象にできます。

      table_create Items TABLE_HASH_KEY ShortText
      column_create Items price COLUMN_SCALAR UInt32
      column_create Items tag COLUMN_SCALAR ShortText
      
      load --table Items
      [
      {"_key": "Book",  "price": 1000, "tag": "A"},
      {"_key": "Note",  "price": 1000, "tag": "B"},
      {"_key": "Box",   "price": 500,  "tag": "B"},
      {"_key": "Pen",   "price": 500,  "tag": "A"},
      {"_key": "Food",  "price": 500,  "tag": "C"},
      {"_key": "Drink", "price": 300,  "tag": "B"}
      ]
      
      select Items \
        --filter true \
        --drilldowns[tag].keys tag \
        --drilldowns[tag].output_columns _key,_nsubrecs,score_mean \
        --drilldowns[tag].columns[score_mean].stage group \
        --drilldowns[tag].columns[score_mean].type Float \
        --drilldowns[tag].columns[score_mean].flags COLUMN_SCALAR \
        --drilldowns[tag].columns[score_mean].value 'aggregator_mean(_score)'
      [
        [
          0,
          0.0,
          0.0
        ],
        [
          [
            [
              6
            ],
            [
              [
                "_id",
                "UInt32"
              ],
              [
                "_key",
                "ShortText"
              ],
              [
                "price",
                "UInt32"
              ],
              [
                "tag",
                "ShortText"
              ]
            ],
            [
              1,
              "Book",
              1000,
              "A"
            ],
            [
              2,
              "Note",
              1000,
              "B"
            ],
            [
              3,
              "Box",
              500,
              "B"
            ],
            [
              4,
              "Pen",
              500,
              "A"
            ],
            [
              5,
              "Food",
              500,
              "C"
            ],
            [
              6,
              "Drink",
              300,
              "B"
            ]
          ],
          {
            "tag": [
              [
                3
              ],
              [
                [
                  "_key",
                  "ShortText"
                ],
                [
                  "_nsubrecs",
                  "Int32"
                ],
                [
                  "score_mean",
                  "Float"
                ]
              ],
              [
                "A",
                2,
                1.0
              ],
              [
                "B",
                3,
                1.0
              ],
              [
                "C",
                1,
                1.0
              ]
            ]
          }
        ]
      ]
      
  • [インデックス構築] VC++版の静的インデックス構築のパフォーマンスを改善しました。

  • [select] JSON形式で出力する際に NaNInfinity-Infinity の代わりに null を出力するようにしました。

    • これらの値はJSONではサポートされていないためです。

  • [select] 標準偏差の集計をサポートしました。

    • 例えば、以下のようにグループごとの標準偏差を計算できます。

      table_create Items TABLE_HASH_KEY ShortText
      column_create Items price COLUMN_SCALAR UInt32
      column_create Items tag COLUMN_SCALAR ShortText
      
      load --table Items
      [
      {"_key": "Book",  "price": 1000, "tag": "A"},
      {"_key": "Note",  "price": 1000, "tag": "B"},
      {"_key": "Box",   "price": 500,  "tag": "B"},
      {"_key": "Pen",   "price": 500,  "tag": "A"},
      {"_key": "Food",  "price": 500,  "tag": "C"},
      {"_key": "Drink", "price": 300,  "tag": "B"}
      ]
      
      select Items \
        --drilldowns[tag].keys tag \
        --drilldowns[tag].output_columns _key,_nsubrecs,price_sd \
        --drilldowns[tag].columns[price_sd].stage group \
        --drilldowns[tag].columns[price_sd].type Float \
        --drilldowns[tag].columns[price_sd].flags COLUMN_SCALAR \
        --drilldowns[tag].columns[price_sd].value 'aggregator_sd(price)' \
        --output_pretty yes
      [
        [
          0,
          1594339851.924836,
          0.002813816070556641
        ],
        [
          [
            [
              6
            ],
            [
              [
                "_id",
                "UInt32"
              ],
              [
                "_key",
                "ShortText"
              ],
              [
                "price",
                "UInt32"
              ],
              [
                "tag",
                "ShortText"
              ]
            ],
            [
              1,
              "Book",
              1000,
              "A"
            ],
            [
              2,
              "Note",
              1000,
              "B"
            ],
            [
              3,
              "Box",
              500,
              "B"
            ],
            [
              4,
              "Pen",
              500,
              "A"
            ],
            [
              5,
              "Food",
              500,
              "C"
            ],
            [
              6,
              "Drink",
              300,
              "B"
            ]
          ],
          {
            "tag": [
              [
                3
              ],
              [
                [
                  "_key",
                  "ShortText"
                ],
                [
                  "_nsubrecs",
                  "Int32"
                ],
                [
                  "price_sd",
                  "Float"
                ]
              ],
              [
                "A",
                2,
                250.0
              ],
              [
                "B",
                3,
                294.3920288775949
              ],
              [
                "C",
                1,
                0.0
              ]
            ]
          }
        ]
      ]
      
      • aggregate_sd(target, {"unbiased": true}) と指定することで、不偏標準偏差も計算できます。

  • [Windows] Visual Studio 2013のサポートをやめました。

修正#

  • [Groonga HTTPサーバー] 応答がエラーで中断された時に、 shutdown?immediate を実行しても、リクエストが中断しない問題を修正しました。

  • リクエスト中にエラーが発生した時にクラッシュする問題を修正しました。

    • これは、Apache Arrow形式を使っている時にのみ発生します。

    • 前のリクエストがエラーによって中断された後に再度Groongaへリクエストを送信した時にGroongaがクラッシュします。

  • [between] 一時テーブルを使用した時にクラッシュする問題を修正しました。

    • 例えば、 between の第一引数に動的カラムを指定すると、Groongaがクラッシュしていました。

  • プラグインで作成したプロシージャーが予期せず解放される問題を修正しました。

    • 参照カウントモードでのみ発生します。

    • plugin_register を使っていない場合は、発生しません。

    • plugin_register を実行したプロセスでは発生しません。

    • plugin_register を実行していないプロセスで発生します。

  • token_column を使った静的インデックス構築中に正規化エラーが発生する問題を修正しました。[GitHub#1122][naoaさんの報告]

感謝#

  • naoaさん

10.0.4リリース - 2020-06-29#

改良#

  • [テーブル] ハッシュテーブルで4億件のレコードの登録をサポートしました。

  • [select] _score が再帰的に値を取得しない時のパフォーマンスを改善しました。

    • Groongaは、検索結果が検索対象の時に、 _score の値を再帰的に取得します。

    • 例えば、 slices は検索結果が検索対象です。したがって、 slices を使っているクエリーでは、この改善は効果がありません。

  • [ログ] ドリルダウンのキーをクエリーログに出力するようにしました。

  • [reference_acquire], [reference_release] 参照カウントモード用に新しいコマンドを追加しました。

    • 短い間隔で複数の load を呼び出す必要がある場合、参照カウントモードによる自動クローズによってパフォーマンスが低下します。

    • 複数の load の前に /reference_acquire を呼び、 複数の load の後に /reference_release を呼ぶことで、このパフォーマンスの低下を避けることができます。/reference_acquire/reference_release の間は自動クローズは無効になります。

      • /reference_acquire が、対象のオブジェクトの参照を取得するためです。

    • パフォーマンスに影響のある操作が完了したら、 /reference_release を呼ぶ必要があります。

    • /reference_release を呼ばない場合、参照カウントモードは機能しません。

  • [select] 一度の drilldown で複数グループの集計をサポートしました。

    • 以下のように、一回の drilldown で異なるグループ毎に和と算術平均を計算できるようになりました。

      table_create Items TABLE_HASH_KEY ShortText
      column_create Items price COLUMN_SCALAR UInt32
      column_create Items quantity COLUMN_SCALAR UInt32
      column_create Items tag COLUMN_SCALAR ShortText
      
      load --table Items
      [
      {"_key": "Book",  "price": 1000, "quantity": 100, "tag": "A"},
      {"_key": "Note",  "price": 1000, "quantity": 10,  "tag": "B"},
      {"_key": "Box",   "price": 500,  "quantity": 15,  "tag": "B"},
      {"_key": "Pen",   "price": 500,  "quantity": 12,  "tag": "A"},
      {"_key": "Food",  "price": 500,  "quantity": 111, "tag": "C"},
      {"_key": "Drink", "price": 300,  "quantity": 22,  "tag": "B"}
      ]
      
      select Items \
        --drilldowns[tag].keys tag \
        --drilldowns[tag].output_columns _key,_nsubrecs,price_sum,quantity_sum \
        --drilldowns[tag].columns[price_sum].stage group \
        --drilldowns[tag].columns[price_sum].type UInt32 \
        --drilldowns[tag].columns[price_sum].flags COLUMN_SCALAR \
        --drilldowns[tag].columns[price_sum].value 'aggregator_sum(price)' \
        --drilldowns[tag].columns[quantity_sum].stage group \
        --drilldowns[tag].columns[quantity_sum].type UInt32 \
        --drilldowns[tag].columns[quantity_sum].flags COLUMN_SCALAR \
        --drilldowns[tag].columns[quantity_sum].value 'aggregator_sum(quantity)'
      [
        [
          0,
          0.0,
          0.0
        ],
        [
          [
            [
              6
            ],
            [
              [
                "_id",
                "UInt32"
              ],
              [
                "_key",
                "ShortText"
              ],
              [
                "price",
                "UInt32"
              ],
              [
                "quantity",
                "UInt32"
              ],
              [
                "tag",
                "ShortText"
              ]
            ],
            [
              1,
              "Book",
              1000,
              100,
              "A"
            ],
            [
              2,
              "Note",
              1000,
              10,
              "B"
            ],
            [
              3,
              "Box",
              500,
              15,
              "B"
            ],
            [
              4,
              "Pen",
              500,
              12,
              "A"
            ],
            [
              5,
              "Food",
              500,
              111,
              "C"
            ],
            [
              6,
              "Drink",
              300,
              22,
              "B"
            ]
          ],
          {
            "tag": [
              [
                3
              ],
              [
                [
                  "_key",
                  "ShortText"
                ],
                [
                  "_nsubrecs",
                  "Int32"
                ],
                [
                  "price_sum",
                  "UInt32"
                ],
                [
                  "quantity_sum",
                  "UInt32"
                ]
              ],
              [
                "A",
                2,
                1500,
                112
              ],
              [
                "B",
                3,
                1800,
                47
              ],
              [
                "C",
                1,
                500,
                111
              ]
            ]
          }
        ]
      ]
      
  • [groonga-httpd] スタンドアローンモードで、 --pid-path をサポートしました。

    • 以前のバージョンのスタンドアローンモードでは、 --pid-path は無視されていました。

  • [io_flush] 参照カウントモードに対応しました。

  • [logical_range_filter],[logical_count] 参照カウントモードに対応しました。

  • [Groonga HTTPサーバー] 最後のチャンクの後にヘッダーをつけないようにしました。

    • 最後のチャンクの後のヘッダーを無視するHTTPクライアントが存在する可能性があるためです。

  • [vector_slice] Float32 型のベクターをサポートしました。 [GitHub#1106 naoaさんがパッチ提供]

  • トークンカラムを使った、並列静的インデックス構築をサポートしました。

    • 予めトークナイズされたデータから複数スレッドで静的インデックスの構築ができるようになりました。

    • 以下の環境変数で、並列静的インデックス構築のパラメータを調整できます。

      • GRN_TOKEN_COLUMN_PARALLEL_CHUNK_SIZE : スレッド毎にどのくらいのレコードを処理するかを指定します。

        • デフォルト値は 1024 レコードです。

      • GRN_TOKEN_COLUMN_PARALLEL_TABLE_SIZE_THRESHOLD : どのくらいのソースレコードで並列化するかを指定します。

        • デフォルト値は 102400 レコードです。

  • [select] 参照カウントモード時の load_table のパフォーマンスを改善しました。

修正#

  • シャードをまたいでいて、かつ --filter を指定していない動的カラムを使って検索すると、Gronngaのデータベースが破損する問題を修正しました。

  • schema コマンドの結果に Float32 型が表示されなかった問題を修正しました。

  • 参照 uvector が要素を持っていないとき、 _nsubrecs を余分にカウントする問題を修正しました。

感謝#

  • naoaさん

10.0.3リリース - 2020-05-29#

改良#

  • 予めトークナイズされたデータから転置インデックスを構築できるようになりました。

    • これにより、インデックスの構築が高速化します。

    • この改善を使うには、トークンカラムを準備する必要があります。

    • トークンカラムは、インデックスカラムのように自動で値が生成されます。

    • トークンカラムの値はソースカラムの値をトークナイズすることで生成されます。

    • トークンカラムは以下のようにソースカラムを設定することで作成できます。

      table_create Terms TABLE_PAT_KEY ShortText \
        --normalizer NormalizerNFKC121 \
        --default_tokenizer TokenNgram
      
      table_create Notes TABLE_NO_KEY
      column_create Notes title COLUMN_SCALAR Text
      
      # The last "title" is the source column.
      column_create Notes title_terms COLUMN_VECTOR Terms title
      
  • [select] 関数の引数に vector を指定できるようになりました。

    • 例えば、 queryflags オプションを vector を使って以下のように記述できます。

      select \
        --table Memos \
        --filter 'query("content", "-content:@mroonga", \
                        { \
                          "expander": "QueryExpanderTSV", \
                          "flags": ["ALLOW_LEADING_NOT", "ALLOW_COLUMN"] \
                        })'
      
  • [select] 動的カラムに新しいステージ result_set を追加しました。

    • このステージは、結果セットのテーブルにカラムを作ります。したがって、 queryfilter が存在しない場合は作られません。

      • queryfilter が存在しない場合は、結果セットのテーブルが作られないためです。

    • このステージでは _value は使用できません。 result_set ステージの値は score_column に格納されます。

  • [vector_slice] 重み付きベクターの重みに Float32 型が使えるようになりました。 [GitHub#1106 naoaさんがパッチ提供]

  • [select] drilldownsの動的カラムのステージに filteredoutput を追加しました。 [GitHub#1101 naoaさんがパッチ提供][GitHub#1100 naoaさんがパッチ提供]

    • drilldowns[Label].stage filtereddrilldowns[Label].stage output のように drilldowns の動的カラムのステージに filteredoutput を使えます。

  • [select] ドリルダウンでの集計に Float 型の値をサポートしました。

    • MAXMINSUM を使って Float 型の値の最大値、最小値、合計値を集計できます。

  • [query] [geo_in_rectangle] [geo_in_circle] query()geo_in_rectangle()geo_in_circle() に新しいオプション score_column を追加しました。

    • score_column を使うことで条件毎にスコアの値を格納できます。

    • 通常、Groongaは、全ての条件のスコアーを加算してスコアーを計算しますが、条件毎にスコアーの値を取得したいこともあります。

    • 例えば以下のように、中心座標にどれだけ近いかをスコアーとして使いたい場合に score_column が使えます。

    table_create LandMarks TABLE_NO_KEY
    column_create LandMarks name COLUMN_SCALAR ShortText
    column_create LandMarks category COLUMN_SCALAR ShortText
    column_create LandMarks point COLUMN_SCALAR WGS84GeoPoint
    
    table_create Points TABLE_PAT_KEY WGS84GeoPoint
    column_create Points land_mark_index COLUMN_INDEX LandMarks point
    
    load --table LandMarks
    [
      {"name": "Aries"      , "category": "Tower"     , "point": "11x11"},
      {"name": "Taurus"     , "category": "Lighthouse", "point": "9x10" },
      {"name": "Gemini"     , "category": "Lighthouse", "point": "8x8"  },
      {"name": "Cancer"     , "category": "Tower"     , "point": "12x12"},
      {"name": "Leo"        , "category": "Tower"     , "point": "11x13"},
      {"name": "Virgo"      , "category": "Temple"    , "point": "22x10"},
      {"name": "Libra"      , "category": "Tower"     , "point": "14x14"},
      {"name": "Scorpio"    , "category": "Temple"    , "point": "21x9" },
      {"name": "Sagittarius", "category": "Temple"    , "point": "43x12"},
      {"name": "Capricorn"  , "category": "Tower"     , "point": "33x12"},
      {"name": "Aquarius"   , "category": "mountain"  , "point": "55x11"},
      {"name": "Pisces"     , "category": "Tower"     , "point": "9x9"  },
      {"name": "Ophiuchus"  , "category": "mountain"  , "point": "21x21"}
    ]
    
    select LandMarks \
      --sort_keys 'distance' \
      --columns[distance].stage initial \
      --columns[distance].type Float \
      --columns[distance].flags COLUMN_SCALAR \
      --columns[distance].value 0.0 \
      --output_columns 'name, category, point, distance, _score' \
      --limit -1 \
      --filter 'geo_in_circle(point, "11x11", "11x1", {"score_column": distance}) && category == "Tower"'
    [
      [
        0,
        1590647445.406149,
        0.0002503395080566406
      ],
      [
        [
          [
            5
          ],
          [
            [
              "name",
              "ShortText"
            ],
            [
              "category","ShortText"
            ],
            [
              "point",
              "WGS84GeoPoint"
            ],
            [
              "distance",
              "Float"
            ],
            [
              "_score",
              "Int32"
            ]
          ],
          [
            "Aries",
            "Tower",
            "11x11",
            0.0,
            1
          ],
          [
            "Cancer",
            "Tower",
            "12x12",
            0.0435875803232193,
            1
          ],
          [
            "Leo",
            "Tower",
            "11x13",
            0.06164214760065079,
            1
          ],
          [
            "Pisces",
            "Tower",
            "9x9",
            0.0871751606464386,
            1
          ],
          [
            "Libra",
            "Tower",
            "14x14",
            0.1307627409696579,
            1
          ]
        ]
      ]
    ]
    
    • 上記の例では、 _score によるソートは意味をなしません。 category == "Tower" によって、 _score の値は全て 1 になるためです。しかし、 socre_column を使うことで、中心座標からの距離でソートできます。

  • [Windows] クラッシュしていないくてもエラー時にはバックトレースが出力されるようになりました。

  • [Windows] 古いWindowsのサポートをやめました。

    • 10.0.3から、Windows 8 (Windows Server 2012) 以降を要求します。

  • [select] 参照可能なソートキーとそうでないソートキーが混在しているときのソートパフォーマンスを改善しました。

    • 参照可能なソートキーとそうでないソートキーが混在していて、参照可能なキーが2つ以上あるときのソートパフォーマンスを改善しました。

      • 参照可能なソートキーとは以下のソートキー以外のことです。

        • 圧縮されたカラム

        • ドリルダウンのキーに複数の値が指定されているドリルダウンの値を格納する _value

        • ShortText 型のキーを持たないパトリシアトライテーブルの _key

        • _score

    • 文字列以外のソートキーが多いほど、ソートに使用するメモリ使用量が少なくなります。

  • [select] 全てのソートキーが参照可能なキーの時のソートのパフォーマンスを改善しました。

  • [select] _socre = column1*X + column2*Y + ... の場合のスコアラーのパフォーマンスを改善しました。

    • この最適化は、 _score 内に多くの + または * がある場合に効きます。

    • 現状、 +* に対してのみ効果があります。

  • [select] フレーズ近傍検索をサポートしました。

    • フレーズ単位で近傍検索できます。

      • フレーズ近傍検索のクエリー構文は、 *NP"Phrase1 phrase2 ..." です。

      • フレーズ近傍検索のスクリプト構文は、 column *NP "phrase1 phrase2 ..." です。

      • 検索対象のフレーズにスペースを含む場合、 以下のようにフレーズを " で囲うことで検索できます。

        table_create Entries TABLE_NO_KEY
        column_create Entries content COLUMN_SCALAR Text
        
        table_create Terms TABLE_PAT_KEY ShortText \
          --default_tokenizer 'TokenNgram("unify_alphabet", false, \
                                          "unify_digit", false)' \
          --normalizer NormalizerNFKC121
        column_create Terms entries_content COLUMN_INDEX|WITH_POSITION Entries content
        
        load --table Entries
        [
        {"content": "I started to use Groonga. It's very fast!"},
        {"content": "I also started to use Groonga. It's also very fast! Really fast!"}
        ]
        
        select Entries --filter 'content *NP "\\"I started\\" \\"use Groonga\\""' --output_columns 'content'
        [
          [
            0,
            1590469700.715882,
            0.03997230529785156
          ],
          [
            [
              [
                1
              ],
              [
                [
                  "content",
                  "Text"
                ]
              ],
              [
                "I started to use Groonga. It's very fast!"
              ]
            ]
          ]
        ]
        
  • [ベクターカラム] 重み付きベクターの重みに float32 型を追加しました。

    • uint32 の代わりに float32 として重みを格納できます。

    • この機能を使うには、 column_create 実行時に WEIGHT_FLOAT32 フラグを追加する必要があります。

      column_create Records tags COLUMN_VECTOR|WITH_WEIGHT|WEIGHT_FLOAT32 Tags
      
    • 今の所、 WEIGHT_FLOAT32 フラグは、 COLUMN_INDEX フラグと併用できません。

  • 以下のAPIを公開しました。

    • grn_obj_is_xxx 関数を追加しました。詳細は以下の通りです。

      • grn_obj_is_weight_vector(grn_ctx *ctx, grn_obj *obj)

        • 重み付きベクターかどうかを bool として返します。

      • grn_obj_is_uvector(grn_ctx *ctx, grn_obj *obj)

        • uvector かどうかを bool として返します。

          • uvector とは、要素のサイズが固定の vector です。

      • grn_obj_is_weight_uvector(grn_ctx *ctx, grn_obj *obj)

        • 重み付きuvectorかどうかを bool として返します。

    • grn_type_id_size(grn_ctx *ctx, grn_id id) を追加しました。

      • Groongaのデータ型のサイズを size_t として返します。

    • grn_selector_data_get_xxx を追加しました。詳細は以下の通りです。

      • これらの関数はセレクター関連のデータを返します。

        • これらの関数はセレクターの中で呼び出すことを想定しています。セレクター以外の場所で呼び出された場合は、 NULL を返します。

          • grn_selector_data_get(grn_ctx *ctx)

            • セレクター呼び出しに関する全ての情報を grn_selector_data * 構造体として返します。

          • grn_selector_data_get_selector(grn_ctx *ctx, grn_selector_data *data)

            • セレクター自身を grn_obj * として返します。

          • grn_selector_data_get_expr(grn_ctx *ctx, grn_selector_data *data)

            • セレクターに使用されている、 --filter 条件や --query 条件を grn_obj * として返します。

          • grn_selector_data_get_table(grn_ctx *ctx, grn_selector_data *data)

            • 検索対象のテーブルを grn_obj * として返します。

          • grn_selector_data_get_index(grn_ctx *ctx, grn_selector_data *data)

            • セレクターに使われているインデックスを grn_obj * として返します。

          • grn_selector_data_get_args(grn_ctx *ctx, grn_selector_data *data, size_t *n_args)

            • セレクターが呼び出した関数の引数を grn_obj * として返します。

          • grn_selector_data_get_result_set(grn_ctx *ctx, grn_selector_data *data)

            • 結果テーブルを grn_obj * として返します。

          • grn_selector_data_get_op(grn_ctx *ctx, grn_selector_data *data)

            • 既存の結果セットに対してどう集合演算したかを grn_operator として返します。

    • grn_plugin_proc_xxx 関数を追加しました。詳細は以下の通りです。

      • grn_plugin_proc_get_value_operator(grn_ctx *ctx, grn_obj *value, grn_operator default_operator, const char *context)

        • クエリーオペレーターを grn_operator として返します。

          • 例えば、 &&GRN_OP_ANDP として返されます。

      • grn_plugin_proc_get_value_bool(grn_ctx *ctx, grn_obj *value, bool default_value, const char *tag)

        • 以下の関数の引数 with_transposition のように true または false が指定される値を bool として返します。( bool はC言語のデータ型です。)

          fuzzy_search(column, query, {"max_distance": 1, "prefix_length": 0, "max_expansion": 0, "with_transposition": true})
          
    • grn_proc_options_xxx 関数を追加しました。詳細は以下の通りです。

      • これらは、 query() でのみ使えます。

        • grn_proc_options_parsev(grn_ctx *ctx, grn_obj *options, const char *tag, const char *name, va_list args) を追加しました。

          • オプションのパースを実行します。

          • 今までは、オプションのパースを自分で実装しなければなりませんでしたが、この関数を呼び出すだけでオプションをパースできます。

        • grn_proc_options_parse(grn_ctx *ctx, grn_obj *options, const char *tag, const char *name, ...)

          • grn_proc_option_parsev() を呼び出します。したがって、この関数の機能は、 grn_proc_options_parsev() と同じです。

          • grn_proc_options_parsev() とは、インターフェースだけが異なります。

    • grn_text_printfv(grn_ctx *ctx, grn_obj *bulk, const char *format, va_list args) を追加しました。

      • grn_text_vprintf は10.0.3から非推奨になりました。 代わりに grn_text_printfv を使ってください。

    • grn_type_id_is_float_family(grn_ctx *ctx, grn_id id) を追加しました。

      • grn_type_idGRN_DB_FLOAT32 または GRN_DB_FLOAT かどうかを bool として返します。

    • grn_dat_cursor_get_max_n_records(grn_ctx *ctx, grn_dat_cursor *c) を追加しました。

      • カーソルが保持できるレコード数の最大値を size_t として返します。(このAPIはDATテーブル用です。)

    • grn_table_cursor_get_max_n_records(grn_ctx *ctx, grn_table_cursor *cursor) を追加しました。

      • カーソルが保持できるレコード数の最大値を返します。

      • 全ての種類(TABLE_NO_KEY, TABLE_HASH_KEY, TABLE_DAT_KEY, TABLE_PAT_KEY)のテーブルで使えます。

    • grn_result_set_add_xxx を追加しました。詳細は以下の通りです。

      • grn_result_set_add_record(grn_ctx *ctx, grn_hash *result_set, grn_posting *posting, grn_operator op)

        • 結果セットのテーブルにレコードを追加します。

        • grn_ii_posting_add_float は10.0.3から非推奨になりました。代わりに grn_rset_add_records() を使ってください。

      • grn_result_set_add_table(grn_ctx *ctx, grn_hash *result_set, grn_obj *table, double score, grn_operator op)

        • 結果セットにテーブルを追加します。

      • grn_result_set_add_table_cursor(grn_ctx *ctx, grn_hash *result_set, grn_table_cursor *cursor, double score, grn_operator op)

        • 結果セットにカーソル内のレコードを追加します。

    • grn_vector_copy(grn_ctx *ctx, grn_obj *src, grn_obj *dest) を追加しました。

      • vector オブジェトをコピーします。 vector オブジェクトのコピーに成功したかどうかを返します。

    • grn_obj_have_source(grn_ctx *ctx, grn_obj *obj) を追加しました。

      • ソースカラムを持つカラムかどうかを bool として返します。

    • grn_obj_is_token_column(grn_ctx *ctx, grn_obj *obj) を追加しました。

      • トークンカラムかどうかを bool として返します。

    • grn_hash_add_table_cursor(grn_ctx *ctx, grn_hash *hash, grn_table_cursor *cursor, double score) を追加しました。

      • 結果セットを一括して挿入するための関数です。 grn_ii_posting_add() を使ってレコードを挿入するより高速です。

修正#

  • 複数のスレッドから、同時にモジュール(トークナイザー、ノーマライザー、トークンフィルター)が使われた場合にクラッシュする問題を修正しました。

  • Float32 の値を表示する際の精度を修正しました。

    • 10.0.3から Float32 の値の精度は、 8桁から7桁になります。

  • 動的カラムのパラメーターだけが違うクエリーが実行された時にGroongaが誤ったキャッシュを使用していた問題を修正しました。 [GitHub#1102 naoaさんがパッチ提供]

感謝#

  • naoaさん

10.0.2リリース - 2020-04-29#

改良#

  • time_classify_* 関数が uvector に対応しました。 [GitHub#1089][naoaさんがパッチ提供]

    • uvector とは、要素のサイズが固定のベクターです。

    • 例えば、Time型の要素を格納しているベクターは uvector です。

  • ゼロコピーで値を参照できないソートキーが混在しているケースでソートのパフォーマンスを改善しました。

    • いくつかのソートキー(例えば、 _score 等)の値はゼロコピーで値を参照できません。

    • これらの値が一つでも含まれる場合、以前は全てのソートキーの値をコピーしていました。

    • 今回の変更から、参照できないソートキーの値だけコピーし、参照可能なソートキーの値はコピーせずに参照するようにしました。

    • ただ、この変更で全てのソートキーの値が参照可能なケースでパフォーマンスが落ちる可能性があります。

  • 重み付きベクターをJSON文字列としてロードできるようにしました。

    • 以下の例のように、重み付きベクターをJSON文字列としてロードできます。

      table_create Tags TABLE_PAT_KEY ShortText
      table_create Data TABLE_NO_KEY
      column_create Data tags COLUMN_VECTOR|WITH_WEIGHT Tags
      column_create Tags data_tags COLUMN_INDEX|WITH_WEIGHT Data tags
      load --table Data
      [
        {"tags": "{\"fruit\": 10, \"apple\": 100}"},
        {"tags": "{\"fruit\": 200}"}
      ]
      
  • Float32 型をサポートしました。

    • Groongaは既に Float 型を持っていますが、これは、倍精度浮動小数点数です。したがって、単精度浮動小数点数のみを使う場合は、効率が悪いです。

    • Float32 型を追加することで、より適切な型を選択できるようになりました。

  • 以下のAPIを公開しました。

    • grn_obj_unref(grn_ctx *ctx, grn_obj *obj)

      • このAPIは参照カウントモードのときのみ使用します。(参照カウントモードとは、 GRN_ENABLE_REFERENCE_COUNT=yes の状態のことです。)

        • このAPIは、参照カウントモードの時のみ grn_obj_unlink() を呼び出します。参照カウントモード以外の時は、何もしません。

        • 参照カウントモードの時のみ grn_obj_unlink() を呼び出す必要がある時に便利です。

        • 以下の例のように、参照カウントモードかどうかの条件を書かなくて良くなるためです。

          • grn_obj_unref() を使用しない場合の例です。

            if (grn_enable_reference_count) {
             grn_obj_unlink(ctx, obj);
            }
            
          • grn_obj_ubref() を使用する場合の例です。

            grn_obj_ubref(ctx, obj);
            
    • grn_get_version_major(void)

    • grn_get_version_minor(void)

    • grn_get_version_micro(void)

      • uint32_t としてGroongaのメジャー、マイナー、マイクロバージョンを返します。

    • grn_posting_get_record_id(grn_ctx *ctx, grn_posting *posting)

    • grn_posting_get_section_id(grn_ctx *ctx, grn_posting *posting)

    • grn_posting_get_position(grn_ctx *ctx, grn_posting *posting)

    • grn_posting_get_tf(grn_ctx *ctx, grn_posting *posting)

    • grn_posting_get_weight(grn_ctx *ctx, grn_posting *posting)

    • grn_posting_get_weight_float(grn_ctx *ctx, grn_posting *posting)

    • grn_posting_get_rest(grn_ctx *ctx, grn_posting *posting)

      • これらは、ポスティングリストの情報を返します。

      • これらのAPIは、 grn_posting_get_weight_float 以外は、 uint32_t として値を返します。

      • grn_posting_get_weight_floatfloat として値を返します。

      • grn_posting_get_section_id(grn_ctx *ctx, grn_posting *posting)

        • セクションIDとはカラム名の内部表現です。

        • カラム名を文字列としてポスティングリストに格納すると、情報量が多くなり無駄な容量を使います。

        • したがって、カラム名をセクションIDという数値としてポスティングリストに格納することで、情報量を圧縮し使用する容量を少なくしています。

      • grn_posting_get_tf(grn_ctx *ctx, grn_posting *posting)

        • grn_posting_get_tftf とは、単語の出現頻度です。

      • grn_posting_get_weight_float(grn_ctx *ctx, grn_posting *posting)

        • トークンの重みを float として返します。

        • 今後はトークンの重みを取得する際はこのAPIを使用することをおすすめします。

          • 近い将来、重みは内部的に uint32_t から float に変更するためです。

修正#

  • 32bit GUN/Linux等でGroongaがクラッシュすることがある問題を修正しました。

  • 関係のないカラムの値をクリアーしてしまう問題を修正しました。 [GitHub#1087][sutaminさんの報告]

  • dump コマンドでレコードをダンプした時にメモリリークする問題を修正しました。

  • output_columns に無効な値を指定した時にメモリリークする問題を修正しました。

  • snippet 関数を実行する時にメモリリークする問題を修正しました。

  • 以下の条件を満たした時にメモリリークする問題を修正しました。

    • initial ステージで動的カラムを使用した場合。

    • select コマンドの引数 slices を使用した場合。

  • logical_table_remove でテーブルを削除した際にメモリリークする問題を修正しました。

  • 参照カウントモードを使用した時にメモリリークする問題を修正しました。

    • 参照カウントモードとは、 GRN_ENABLE_REFERENCE_COUNT=yes の状態のことです。

    • この機能は実験的です。パフォーマンスが低下することがあります。

  • Apache Arrow形式でデータをロードした際に _key アクセサーを解放しすぎる問題を修正しました。

感謝#

  • sutaminさん

  • naoaさん

10.0.1リリース - 2020-03-30#

Groonga 10.0.0 のUbuntuとWindows(VC++版)のパッケージに誤りがあったため Groonga 10.0.1 をリリースしました。

既にCentOS、Debian、Windows(MinGW版)のGroonga 10.0.0を使用している方は、そのまま使っていただいて問題ありません。

修正#

  • Windows(VC++版)のパッケージに不足していたランタイム(vcruntime140_1.dll)を追加しました。

10.0.0リリース - 2020-03-29#

改良#

  • [httpd] バンドルしているnginxのバージョンを1.17.9に更新しました。

  • [httpd] 出力形式を拡張子として指定できるようにしました。

    • 例えば、 load?output_type=json の代わりに load.json と書けます。

  • [ログ] Linuxのdumpレベルのログにオープンしたファイルとクローズしたファイルのパスを出力するようにしました。

  • [ログ] Windowsのdebugレベルのログにオープンしたファイルとクローズしたファイルのパスを出力するようにしました。

  • 以下のAPIとマクロを追加しました。

    • grn_timeval_from_double(grn_ctx, double)

      • このAPIは、 double 型を grn_timeval 型に変換します。

      • grn_timeval 型の値を返します。

    • GRN_TIMEVAL_TO_NSEC(timeval)

      • このマクロは、 grn_timeval 型の値を uint64_t 型の値としてナノ秒に変換します。

    • GRN_TIME_USEC_TO_SEC(usec)

      • このマクロは、ミリ秒を秒に変換します。

  • 以下のマクロを非推奨にしました。

    • GRN_OBJ_FORMAT_FIN(grn_ctx, grn_obj_format)

      • 10.0.0から代わりに grn_obj_format_fin(grn_ctx, grn_obj_format) を使ってください。

  • [logical_range_filter],[dump] ストリーム出力に対応しました。

    • この機能は command_version 3 以降で使えます。headerがbodyの後に出力されます。

    • 現在、この機能をサポートしているのは、 dumplogical_range_filter のみです。

    • logical_range_filter は、 command_version 3 以降では、常に出力がstreamとして返ります。

    • この機能は以下の制限があります。

      • limit に指定できる負の値は -1 のみです。

      • MessagePack形式の出力はサポートしていません。

    • この変更で、JSONの応答内容を少し変更しています。

      • 以下のように以前のバージョンとは、キーの順序が異なっています。

        • 以前のバージョンのキーの順序

          {
            "header": {...},
            "body": {...}
          }
          
        • 本バージョン(10.0.0)のキーの順序

          {
            "body": {...},
            "header": {...}
          }
          
    • dumplogical_range_filtercommand_version 3 で実行した時はキャッシュが効きません。

      • 10.0.0から dumplogical_range_filtercommand_version 3 の時にストリームで応答を返すので、応答全体をキャッシュできないためです。

  • [logical_range_filter] Apache Arrow形式での応答をサポートしました。

    • 以下のデータ型をサポートしています。

      • UInt8

      • Int8

      • UInt16

      • Int16

      • UInt32

      • Int32

      • UInt64

      • Int64

      • Time

      • ShortText

      • Text

      • LongText

      • Vector of Int32

      • Reference vector

  • Ubuntu 20.04 (Focal Fossa)をサポートしました。

  • Ubuntu 19.04 (Disco Dingo)のサポートをやめました。

    • このバージョンはEOLになっているためです。