お知らせ - 16系 — Groonga v16.1.0ドキュメント

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

# お知らせ - 16系

## 16.1.0リリース - 2026-08-28

### 修正

#### 新しいセグメントの確保に失敗した時にクラッシュする問題を修正

この問題は、メモリー不足や、メモリーマップ数の上限に到達しているような環境で、インデックスの更新時に発生することがあります。

Groongaは、インデックスの更新に必要な領域が確保出来ない時にエラーメッセージを出力しますが、そのエラーメッセージ内で未初期化の領域を参照していました。

このエラーメッセージは、Groongaがメモリ不足やメモリーマップ数の上限に到達していて、メモリーを確保できない時にのみ生成されます。よって、メモリーに余裕のある環境では発生しません。

## 16.0.9リリース - 2026-08-07

### 改良

#### [benchmark] `G_GNUC_CONST`の誤った使い方を削除

GH-2857 correctmostさんの報告。

GH-2858 correctmostさんのパッチ提供。

最新のGCCとの互換性のための変更です。詳細は、 https://gitlab.gnome.org/GNOME/glib/-/commit/016829559 を参照してください。

#### [string_truncate] 新しい関数 `string_truncate()` を追加

`string_truncate()`は、文字列を指定された文字数以下に切り詰めます。文字列が切り詰められた場合、残された文字の末尾を省略記号に置き換えます。その結果、省略記号を含めて`length`文字の長さになります。これはRuby on Railsの`String#truncate`と同様の動作です。

実行例：

    plugin_register functions/string

    table_create Memos TABLE_HASH_KEY ShortText
    load --table Memos
    [
    {"_key": "Groonga is a full text search engine"}
    ]

    select Memos \
      --output_columns '_key, string_truncate(_key, 15)'
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         1
    #       ],
    #       [
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "string_truncate",
    #           null
    #         ]
    #       ],
    #       [
    #         "Groonga is a full text search engine",
    #         "Groonga is a..."
    #       ]
    #     ]
    #   ]
    # ]

#### 新しい関数 `binary_length()` を追加

`binary_length()` はカラム内のデータのバイト数を返します。以下のように、各カラムのデータサイズを確認できます。

    plugin_register functions/binary

    table_create Memos TABLE_HASH_KEY ShortText

    load --table Memos
    [
    {"_key": "ぐるんが"},
    {"_key": "Groonga"}
    ]

    select Memos \
      --output_columns '_key, binary_length(_key)'
    #[
    #  [
    #    0,
    #    1786079749.354771,
    #    0.0005497932434082031
    #  ],
    #  [
    #    [
    #      [
    #        2
    #      ],
    #      [
    #        [
    #          "_key",
    #          "ShortText"
    #        ],
    #        [
    #          "binary_length",
    #          null
    #        ]
    #      ],
    #      [
    #        "ぐるんが",
    #        12
    #      ],
    #      [
    #        "Groonga",
    #        7
    #      ]
    #    ]
    #  ]
    #]

#### [normalizers] Unicode 17.0.0をサポート

### 修正

#### ノーマライザーを複数使用したときに、意図せず空白が無視されてトークナイズされてしまう問題を修正

GH-2853 askdkcさんの報告。

例えば、この問題が原因で、"sayuri"で以下のテキストがマッチしてしまいます。

    nanakusa yurine konnyaku

しかし、このテキストには、"sayuri"は含まれていません。

この問題は、以下のように複数のノーマライザーを使ったときにのみ発生します：

    table_create Normalizations TABLE_PAT_KEY ShortText
    column_create Normalizations normalized COLUMN_SCALAR ShortText
    load --table Normalizations
    [
    {"_key": "Anything", "normalized": "Whatever"}
    ]

    table_create EntriesChained TABLE_NO_KEY
    column_create EntriesChained content COLUMN_SCALAR Text

    table_create TermsChained TABLE_PAT_KEY ShortText \
      --default_tokenizer 'TokenNgram("unify_alphabet", false)' \
      --normalizers 'NormalizerNFKC150, NormalizerTable("normalized", "Normalizations.normalized")'
    column_create TermsChained content_index COLUMN_INDEX|WITH_POSITION EntriesChained content

    load --table EntriesChained
    [
    {"content": "nanakusa yurine konnyaku"}
    ]

    select EntriesChained \
      --match_columns content \
      --query sayuri \
      --output_columns _id,content
    [
      [
        0,
        1783649374.310488,
        0.0007901191711425781
      ],
      [
        [
          [
            1
          ],
          [
            [
              "_id",
              "UInt32"
            ],
            [
              "content",
              "Text"
            ]
          ],
          [
            1,
            "nanakusa yurine konnyaku"
          ]
        ]
      ]
    ]

### 感謝

- askdkcさん

- correctmostさん

## 16.0.8リリース - 2026-07-13

### 改良

#### [between] 最初の引数にベクター型の値をサポート

> `between`はまだベクターの値に対してインデックスを使用しないことに注意してください。

以下の例では、`between`はいずれかの要素が指定した範囲に含まれていれば`true`を返します。したがって、`between`を使って、範囲内に少なくとも1つの値を持つレコードを検索できます。

実行例：

    table_create Products TABLE_HASH_KEY ShortText
    # [[0,1337566253.89858,0.000355720520019531],true]
    column_create Products prices COLUMN_VECTOR Int32
    # [[0,1337566253.89858,0.000355720520019531],true]

    load --table Products
    [
    {"_key": "A", "prices": [17, 170, 1700]},
    {"_key": "B", "prices": [18, 180, 1800]},
    {"_key": "C", "prices": [19, 190]},
    {"_key": "D", "prices": [20]},
    {"_key": "E", "prices": [21, 210, 2100]}
    ]
    # [[0,1337566253.89858,0.000355720520019531],5]

    select Products --filter 'between(prices, 18, "include", 20, "exclude")'
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         2
    #       ],
    #       [
    #         [
    #           "_id",
    #           "UInt32"
    #         ],
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "prices",
    #           "Int32"
    #         ]
    #       ],
    #       [
    #         2,
    #         "B",
    #         [
    #           18,
    #           180,
    #           1800
    #         ]
    #       ],
    #       [
    #         3,
    #         "C",
    #         [
    #           19,
    #           190
    #         ]
    #       ]
    #     ]
    #   ]
    # ]

#### Debian 12 (bookworm)のサポートをやめました

2026-06-10にEOLになったためです。

### 修正

#### `sort_keys`として`language_model_knn(...)`を指定するとクラッシュする問題を修正

例えば、`sort_keys`に`language_model_knn(text, "male child", {"k" : 2 })`を指定すると、`{ "k" : 2 }`がソート処理内で二重解放されてGroongaがクラッシュします。

#### 空の値に対して`language_model_knn()`を使用した時にクラッシュする問題を修正

以下のように、`language_model_knn()`を空の値に対して使った時にGroongaがクラッシュします：

    plugin_register language_model/knn
    [[0,0.0,0.0],true]

    table_create Data TABLE_NO_KEY
    [[0,0.0,0.0],true]
    column_create Data text COLUMN_SCALAR ShortText
    [[0,0.0,0.0],true]
    column_create Data rabitq_code COLUMN_SCALAR ShortBinary
    [[0,0.0,0.0],true]

    load --table Data
    [
    {"text": "I am a boy."},
    {"text": ""},
    {"text": "This is an apple."}
    ]
    [[0,0.0,0.0],3]

    table_create RaBitQ TABLE_HASH_KEY ShortBinary \
      --default_tokenizer 'TokenLanguageModelKNN("model", \
                                                 "hf:///groonga/all-MiniLM-L6-v2-Q4_K_M-GGUF", \
                                                 "code_column", "rabitq_code")'
    [[0,0.0,0.0],true]
    column_create RaBitQ data_text COLUMN_INDEX Data text
    [[0,0.0,0.0],true]

    select Data   --filter 'language_model_knn(text, "male child")'   --output_columns text

### 実験的な機能

> これは実験的な機能です。現時点ではまだ安定しきっていません。

#### [json_extract] `json_extract()`をサポート

`json_extract()`は、JSONPath式を使ってJSONから値を抽出します。抽出された値は、JSONでの型を保持します。例えば、JSON中の文字列はテキストとして抽出され、JSON中の整数は整数として抽出されます。したがって、`json_extract()`は文字列に対する全文検索と数値に対する範囲検索の両方に使えます。

    table_create Data TABLE_NO_KEY
    # [[0,1337566253.89858,0.000355720520019531],true]
    column_create Data value COLUMN_SCALAR JSON
    # [[0,1337566253.89858,0.000355720520019531],true]

    load --table Data
    [
    {"value": "{\"value\": [[1, 10], [100]]}"},
    {"value": "{\"value\": [[2], [20, 200]]}"},
    {"value": "{\"value\": [[-1, -10], [-100]]}"}
    ]

    select Data --filter 'between(json_extract(value, "$.value[*][*]"), 10, 20)'
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         2
    #       ],
    #       [
    #         [
    #           "_id",
    #           "UInt32"
    #         ],
    #         [
    #           "value",
    #           "JSON"
    #         ]
    #       ],
    #       [
    #         1,
    #         {
    #           "value": [
    #             [
    #               1,
    #               10
    #             ],
    #             [
    #               100
    #             ]
    #           ]
    #         }
    #       ],
    #       [
    #         2,
    #         {
    #           "value": [
    #             [
    #               2
    #             ],
    #             [
    #               20,
    #               200
    #             ]
    #           ]
    #         }
    #       ]
    #     ]
    #   ]
    # ]

#### [ExtractorJSON] `ExtractorJSON`をサポート

> これは実験的な機能です。現時点ではまだ安定しきっていません。

`ExtractorJSON` は`json_extract()`と同様、JSONPath式を使ってJSONデータから値を抽出します。このエクストラクターを使うと、JSONテキスト全体をインデックスすることなく、必要な値だけをJSONからインデックスできます。

`ExtractorJSON` を語彙表に割り当てると、語彙表は抽出された値をインデックスします。元のJSONはデータカラムに保持されます。

以下の例では、JSONカラム中の整数をインデックスします。抽出される値が整数なので、語彙表のキーの型は Int32 です。JSONカラムがロードされるときにインデックスが自動的に使われるため、抽出された値で元のレコードを検索できます。

    table_create Data TABLE_NO_KEY
    # [[0,1337566253.89858,0.000355720520019531],true]
    column_create Data value COLUMN_SCALAR JSON
    # [[0,1337566253.89858,0.000355720520019531],true]
    table_create Numbers TABLE_PAT_KEY Int32 \
      --extractors 'ExtractorJSON("path", "$.value[*][*]")'
    # [[0,1337566253.89858,0.000355720520019531],true]
    column_create Numbers data_value COLUMN_INDEX Data value
    # [[0,1337566253.89858,0.000355720520019531],true]
    load --table Data
    [
    {"value": "{\"value\": [[1, 10], [100]]}"},
    {"value": "{\"value\": [[2], [20, 200]]}"},
    {"value": "{\"value\": [[-1, -10], [-100]]}"}
    ]
    # [[0,1337566253.89858,0.000355720520019531],3]
    select Data --filter 'between(Numbers.data_value, 10, 20)'
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         2
    #       ],
    #       [
    #         [
    #           "_id",
    #           "UInt32"
    #         ],
    #         [
    #           "value",
    #           "JSON"
    #         ]
    #       ],
    #       [
    #         1,
    #         {
    #           "value": [
    #             [
    #               1,
    #               10
    #             ],
    #             [
    #               100
    #             ]
    #           ]
    #         }
    #       ],
    #       [
    #         2,
    #         {
    #           "value": [
    #             [
    #               2
    #             ],
    #             [
    #               20,
    #               200
    #             ]
    #           ]
    #         }
    #       ]
    #     ]
    #   ]
    # ]

## 16.0.5リリース - 2026-05-22

### 修正

#### Windows版のGroongaに必要なDLLが不足していたため起動に失敗する問題を修正

Windows版のGroongaに必要なDLL(`msvcp140_atomic_wait.dll`)を`groonga-16.0.2-x64-vs2022-with-vcruntime.zip`に同梱していませんでした。

この問題は、Windows版のGroonga 16.0.2のみ発生します。

## 16.0.2リリース - 2026-05-07

### 改良

#### Ubuntu 26.04 LTSをサポート

### 修正

#### ODR(One Definition Rule)違反を修正

GH-2787 Nicolas PARLANTさんの報告。

LTO(Link-Time Optimization)を有効にしたビルドが、`grn_tokenizer_query`の重複定義によって失敗していました。この変更で、ODR違反を修正し、LTOを有効にできるようになります。

#### ソースアーカイブのbenchmarkディレクトリーに不足していたファイルを追加

GH-2793 Nicolas PARLANTさんの報告。

不足していたファイルは以下の通りです:

- groonga/benchmark/CMakeLists.txt

- groonga/benchmark/bench-distance.c

- groonga/benchmark/geo-distance-summary.rb

#### "tools"ディレクトリーが重複して作成される問題を修正

GH-2798 Kentaro Hayashiさんの報告。

AlmaLinuxやAmazon Linux向けのgroonga-toolsパッケージをインストールした時、以下のように"tools"ディレクトリーが重複して作成される問題を修正しました。

    /usr/share/groonga/tools/tools/

### 感謝

- Nicolas PARLANTさん

- Kentaro Hayashiさん

## 16.0.1リリース - 2026-03-30

### 改良

#### [language_model_vectorize] `prefix`オプションを追加しました。

入力テキストにプレフィックスを追加できるようになりました。これは`TokenLanguageModelKNN`の`passage_prefix`や`query_prefix`オプションと同様にプレフィックスを必要とするモデルに便利です。

    language_model_vectorize("hf:///groonga/multilingual-e5-base-Q4_K_M-GGUF", \
                             "male child", \
                             {"prefix": "query: "})

#### [object_list] 出力にノーマライザーの情報を追加しました。

`object_list`コマンドの出力に、`normalizers`フィールドが追加され、ノーマライザーの情報を出力するようにしました。

### 修正

#### [HTTP] chunkedリクエストに関する誤ったエラー判定を修正しました。

特定の条件において、有効なHTTPのchunkedリクエストを受け付けたにもかかわらず、エラーで失敗する可能性があるバグを修正しました。

この問題はchunkedリクエストが通信状況などで特定の条件で分割された場合にのみ発生していました。このバグによるエラーが`load`コマンドの実行中に発生した場合、データのロードがすべて完了しないので、再実行が必要になります。

このバグによりインデックスの破損はおこりません。

#### 誤ったfree関数を使用したためにクラッシュが発生するバグを修正しました。

バルクオブジェクトに対して`GRN_OBJ_FIN()`の代わりに`grn_obj_unlink()`を使用していたバグを修正しました。このバグによりクラッシュする可能性がありました。

Daniel Blackさんが報告

関連: https://jira.mariadb.org/browse/MDEV-39098

### 実験的な機能

> これらの機能はまだ実験的で安定していません。これらの機能は、絶対に実運用環境では使わないでください。

#### [データ型] `JSON`型における配列とオブジェクトのサポートを追加しました。

`JSON`型はネストされたデータを含む配列とオブジェクトをサポートするようになりました。これによりすべてのJSONのデータ型がサポートされています。

#### スカラーカラムとFloat32ベクトルカラムに対するOpenZLによる圧縮をサポートしました。

OpenZL によるスカラーカラムとFloat32ベクトルカラムの圧縮をサポートしました。OpenZLはZstandardよりも高い圧縮率を実現できます。

圧縮率の例を示します。

検証に使ったfloat32の配列のデータは次のとおりです:

- 配列の要素数は40,960。

- レコード数は10,000。

圧縮後のサイズ:

- OpenZLによる圧縮: 1.3GB

- Zstandardによる圧縮: 1.5GB

- 圧縮なし: 1.6GB

#### エクストラクターを追加しました。

エクストラクターはGroongaの新しい種類のモジュールのタイプで、トークン化前に構造化データからプレーンテキストを抽出します。

今は`ExtractorHTML`エクストラクターが組み込まれており、それはHTMLタグとHTMLエンティティを削除し、テキストコンテンツのみを抽出します。

次の例は`extract`コマンドを使用して`ExtractorHTML`でテキストを抽出する例です。

    extract \
      --extractors 'ExtractorHTML' \
      --value "<html><body>He&lt;ll&gt;o</body></html>"
    [[0,0.0,0.0],{"extracted":"He<ll>o"}]

### 感謝

- Daniel Blackさん

## 16.0.0リリース - 2026-02-09

毎年恒例の肉の日メジャーリリースです！このリリースには後方互換性が壊れる変更はありません！既存のデータベースを移行せずにGroongaをアップグレードできます。既存のデータベースをそのまま使い続けることができます。

### 修正

#### `TABLE_DAT_KEY`のテーブルでキーでオーバーフローを引き起こす問題を修正

4096byteのキーをセットすると、`TABLE_DAT_KEY`のテーブルが壊れることがあります。