お知らせ - 16系#

16.1.2リリース - 2026-09-29#

改良#

[WASI] groonga コマンドを追加#

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

groonga.mjs はJavaScriptで書かれたWASI向けの groonga コマンドです。 libgroonga.mjs を使っています。

[WASI] Webブラウザ上での実行に対応#

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

WebブラウザはWASIもファイルシステムも提供しません。 そこで libgroonga-web.mjs にはインメモリのファイルシステムで必要なWASI関数を実装しています。データベースは必要に応じてHTTP経由でダウンロードします。examples/web/ に例があるので参照してください。

修正#

[logical_select] コマンドバージョン3のレスポンスが不要な配列になっていた問題を修正#

body は [{...}] でしたが、 select と同じ {...} になりました。

[logical_select] コマンドバージョン3で drilldown (ラベル無し)を指定した際、コマンドバージョン1の形式で出力していた問題を修正#

コマンドバージョン3の形式で出力するようになりました。 select と同様に、 drilldown の各キーが drilldowns のラベルとして使われます。

CMakeパッケージにインストール先の絶対パスが埋め込まれていた問題を修正#

groonga-16.1.1-x64-vs2022.zip のようなCMakeパッケージは、ビルドした場所とは別の場所に展開すると使えませんでした。

16.1.1リリース - 2026-09-23#

改良#

[logical_select] n_workers による並列実行に対応#

--n_workers に -1 または 2 以上を指定すると、 logical_select は次の処理を並列に実行します。

  • 各シャードの検索

  • --drilldown の各キー

  • 依存関係のない --drilldowns[${LABEL}]

依存関係がないとは、 --drilldowns[${LABEL}].table を使用して他のドリルダウンの結果を参照していないことです。他のドリルダウンの結果を参照しているドリルダウンは、参照先のドリルダウンが終わってから実行します。そのため、依存関係があると並列度が下がります。

例えば、合計400万レコードの20個のシャードに対して --n_workers 2 を指定した logical_select は、20コアのマシンで --n_workers 1 を指定した場合より1.5倍高速です。

注意: logical_select を並列に実行すると、次の挙動が変わります。

  • いずれかのシャードの処理が失敗しても、すべてのシャードを処理します。また、最初のエラーを報告します。

  • filter(N)[SHARD] や select(N)[SHARD] といった各シャードのクエリーログは、シャード順ではなく終了順に出力します。

ドリルダウンのクエリーログも改良しました。 drilldown(N) と drilldowns[${LABEL}](N) はキーを出力するようになり、ドリルダウンのフィルター操作は drilldowns[${LABEL}].filter(N) のようにプレフィックスを出力するようになりました。

[logical_select] shard[${LABEL}].table を追加#

logical_select は ${LOGICAL_TABLE}_${YYYYMMDD} という命名規則に基づいて実際のテーブルを自動的に特定します。そのため、この命名規則に従っていない実際のテーブルに対しては logical_select を使えませんでした。

--shard[${LABEL}].table を使って実際のテーブルを明示的に指定できます。

logical_select \
  --shard_key timestamp \
  --shard[1].table Logs_host1 \
  --shard[2].table Logs_host2

${LABEL} は単なるラベルです。これは指定された実際のテーブルを並べ替えるためにのみ使用されます。

1つ以上の --shard[${LABEL}].table を指定した場合、 --logical_table を指定する必要はありません。

注意: --min や --max と一緒に使うとき、ラベルが YYYYMM や YYYYMMDD であっても、シャードの取捨選択には使いません。指定された実際のテーブルをすべて検索します。

[logical_select] sort_keys で shard_key 以外のキーをサポート#

shard_key と同じキーのみをサポートしていました。それ以外のキーも使えるようになりました。検索対象のすべてのシャードのレコードを1つの結果セットとしてソートします。

注意: sort_keys でベクターカラムはまだサポートしていません。また scorer_tf_idf は本来すべてのシャードのレコード数を使って計算すべきですが、各シャード内のレコード数で計算されます。そのため、複数のシャードでは正確なスコアになりません。

各シャードの上位 offset + limit 件を使ってソートするため、ソートのコストは offset + limit に依存します。大きな offset を指定したソートは遅くなります。

[logical_select] slices[${LABEL}] をサポート#

select と同様に、1度の logical_select で複数の検索結果を取得できます。

注意: 現在 select のスライス関連の引数のうち、一部のみをサポートしています。サポートしている引数は logical_select を参照してください。

[logical_select] query_flags をサポート#

select の query_flags と同じものです。

[logical_select] columns[${NAME}].stage=output をサポート#

output ステージの動的カラムは出力対象のレコードに対してだけ作成します。そのため、output_columns の中だけで使う場合は filtered ステージより高速です。

[BFloat16] Float32 から BFloat16 への変換を、最も近い偶数に丸めるようにしました#

これまでは Float32 の下位16ビットを切り捨てていました。これを最も近い偶数に丸めるようにしました。これは Intel AVX512-BF16 や Arm 、TensorFlow、PyTorch などで採用されている標準的な変換方法です。

切り捨て処理には偏りがあり、NaNをInfに変換する場合があります。

注意: 変換後の値は、バージョン16.1.0以前で変換された値とは異なる場合があります。

非推奨となった BFloat16 変換関数#

これらは単なるキャストになりました。キャストを使ってください。

  • grn::numeric::bfloat16_to_float32(): 代わりに static_cast<float>(value) を使ってください。

  • grn::numeric::to_bfloat16(): 代わりに static_cast<grn_bfloat16>(value) を使ってください。

  • grn_bfloat16_to_float32(): 代わりに (float)value を使ってください。

  • grn_float32_to_bfloat16(): 代わりに (grn_bfloat16)value を使ってください。

[WASI] C API をエクスポートする libgroonga.wasm を追加#

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

JavaScript などから使うことができます。 groonga-wasm-${VERSION}.tar.gz という名前でリリースページからダウンロードできます。

libgroonga.wasm を使うユーザーはCコンパイラーを使わないため、ヘッダーは提供していません。libgroonga.wasm はリンクできないため、groonga.pc は提供していません。WASI では groonga コマンドをまだ提供していません。

JavaScript向けに libgroonga.wasm のC APIをラップした便利な libgroonga.mjs も提供しています。

grn_init() は SIGPIPE を無視しなくなりました#

これは libgroonga を組み込んでいるプログラムに対する非互換な変更です。

パイプに書き込むプログラムは、自分で SIGPIPE を処理する必要があります。

修正#

[logical_select] drilldown_calc_target に指定した永続カラムをグループ化後にクローズしていた問題を修正#

永続カラムは他のコンテキストと共有しています。そのため、クラッシュする可能性がありました。

[logical_select] コマンドバージョン3で records が重複していた問題を修正#

1つの結果セットの中に records を複数回出力していました。

浮動小数点数の真偽値が反転して扱われていた問題を修正#

Float と Float32 と BFloat16 では、0.0 を真として、0.0 以外を偽として扱っていました。

そのため、filter や between、load --ifexists の中の !float_column や float_column && ...、... || float_column が正しく動作していませんでした。

[load] BFloat16 の重み付きベクターカラムの重みを2回丸めていた問題を修正#

JSON内の重みを Float32 に変換した後、さらに BFloat16 に変換していました。その結果、直接変換された値とは異なる場合がありました。

例えば1.003906251 を二重に変換した場合は 1.0 でしたが、直接変換では 1.0078125 になります。

distance_cosine() と distance_inner_product() が予期しない値を返すことがある問題を修正#

SIMD実装では、ベクターの終端より後のデータを読む場合がありました。通常は読み込んだデータがゼロであるため結果は正しい値でしたが、以前に使用したバッファでデータが残っていた場合は結果が不正確になっていました。

[autotools] ソースディレクトリ外でのビルドが失敗する問題を修正#

生成するファイル用のビルドディレクトリを作成していませんでした。

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のテーブルが壊れることがあります。