Skip to main content
`Ctrl`+`K`

# お知らせ - 14系

## 14.0.6リリース - 2024-07-29

### 改良

- インデックスを設定していないベクターカラムに対して、前方一致検索ができるようになりました。

  すでに、インデックスを設定したベクターカラムに対しては前方一致検索できますが、インデックスを設定していないベクターカラムに対しては、今まで前方一致検索できませんでした。

  このリリースから、以下のようにインデックスを設定していないベクターカラムに対しても前方一致検索ができます。

      table_create Users TABLE_NO_KEY
      column_create Users name COLUMN_VECTOR ShortText

      load --table Users
      [
      {"name": ["alice"]},
      {"name": ["bob"]},
      {"name": ["callum"]},
      {"name": ["elly", "alice"]},
      {"name": ["marshal"]}
      ]

      select Users --query 'name:^al'
      [
        [
          0,
          0.0,
          0.0
        ],
        [
          [
            [
              2
            ],
            [
              [
                "_id",
                "UInt32"
              ],
              [
                "name",
                "ShortText"
              ]
            ],
            [
              1,
              [
                "alice"
              ]
            ],
            [
              4,
              [
                "elly",
                "alice"
              ]
            ]
          ]
        ]
      ]

- [Debian GNU/Linux] Debian 11 (bullseye) のサポートをやめました。

## 14.0.5リリース - 2024-07-04

### 改良

- CentOS 7のサポートをやめました。

  CentOS 7はEOLになったためです。

- 可能な限りオブジェクト（テーブルやカラム）を削除する機能を追加しました。

  この機能は主にPGroongaのクラッシュセーフ機能で使います。

  PGroongaは`Custom WAL Resource Managers`を使うことで、PGroongaのWALをスタンバイへ自動で適用できるようになります。ただ、`Custom WAL Resource Managers`を使用していると、オブジェクトの破損などでPGroongaのWALの適用に失敗した場合にすべてのレプリケーションが停止します。そのため、壊れたオブジェクトがデータベース内に存在する場合、Groongaはこの機能を使って、できる限り壊れたオブジェクトを削除しようとします。

### 修正

- [query] `query()`の`AND`検索と`OR`検索検索を `'A || query("...", "B C")'` の順で組み合わせたときに、誤った順序で評価される問題を修正しました

  以下の例では、`memo @ "Groonga`の条件がマッチする`{"name": "Alice", "memo": "Groonga user"}`がヒットするはずですが、 この問題が発生した場合はヒットしません。したがって、下記の例では何もヒットしません。

      table_create Users TABLE_NO_KEY
      column_create Users name COLUMN_SCALAR ShortText
      column_create Users memo COLUMN_SCALAR ShortText

      load --table Users
      [
      {"name": "Alice", "memo": "Groonga user"},
      {"name": "Bob",   "memo": "Rroonga user"}
      ]
      select Users \
        --output_columns 'name, memo, _score' \
        --filter 'memo @ "Groonga" || query("name", "Bob Rroonga")'
      [[0,0.0,0.0],[[[0],[["name","ShortText"],["memo","ShortText"],["_score","Int32"]]]]]

  修正後は、以下のように`{"name": "Alice", "memo": "Groonga user"}`がヒットします。

      select Users \
        --output_columns 'name, memo, _score' \
        --filter 'memo @ "Groonga" || query("name", "Bob Rroonga")'
      [
        [
          0,
          1719376617.537505,
          0.002481460571289062
        ],
        [
          [
            [
              1
            ],
            [
              [
                "name",
                "ShortText"
              ],
              [
                "memo",
                "ShortText"
              ],
              [
                "_score",
                "Int32"
              ]
            ],
            [
              "Alice",
              "Groonga user",
              1
            ]
          ]
        ]
      ]

  この問題の発生条件は下記の通りです。

  - `OR`検索と`query()`を組み合わせて使っていること。

  - `query()`内で`AND`検索していること。

  - `'A || query("...", "B C")'`の順序で条件式が記述されていること。

  そのため、`query()`を単独で使用している場合や、`query()`内で`AND`検索をしていない場合は問題ありません。

- [select] `--query "A* OR B"`のように先に前方一致検索を評価する条件が、誤った検索結果を返すことがある問題を修正しました

  この問題は先に前方一致検索を評価する条件の時に発生する可能性があります。 `--query A OR B*`のように最後に前方一致検索を評価するケースでは発生しません。

  この問題が発生すると、以下の`--query "Bo* OR li"`という条件が、`Bo`も`li`も前方一致検索として評価されてしまい`li`の検索結果が誤ったものになります。 `Alice`がヒットするのが期待値ですが、以下のように何もヒットしません。これは、前述の通り`li`が前方一致検索として評価されてしまうためです。

      table_create Users TABLE_NO_KEY
      column_create Users name COLUMN_SCALAR ShortText

      load --table Users
      [
      ["name"],
      ["Alice"]
      ]

      select Users \
        --match_columns name \
        --query "Bo* OR li"
      [
        [
          0,
          1719377505.628048,
          0.0007376670837402344
        ],
        [
          [
            [
              0
            ],
            [
              [
                "_id",
                "UInt32"
              ],
              [
                "name",
                "ShortText"
              ]
            ]
          ]
        ]
      ]

## 14.0.4リリース - 2024-05-29

### 修正

- [query_parallel_or] `query_parallel_or()`を使用すると、match_escalation_threshold または `force_match_escalation` オプションが無視される問題を修正しました。

  修正前は、検索エスカレーションを無効にしても、`query_parallel_or()`使用時はエスカレーションされていました。この問題は、`query_parallel_or()`でのみ発生します。queryでは発生しません。

  一般的には、ヒット数が0件になってしまうのは嬉しくありません。何かしらの検索結果を得たいことが多いです。したがって、通常、検索エスカレーションは無効にしません。そのため、この問題は多くのユーザーには影響がありませんが、以下のようにストップワードを利用しているユーザーには影響があります。

      plugin_register token_filters/stop_word

      table_create Memos TABLE_NO_KEY
      column_create Memos content COLUMN_SCALAR ShortText

      table_create Terms TABLE_PAT_KEY ShortText \
        --default_tokenizer TokenBigram \
        --normalizer NormalizerAuto \
        --token_filters TokenFilterStopWord
      column_create Terms memos_content COLUMN_INDEX|WITH_POSITION Memos content
      column_create Terms is_stop_word COLUMN_SCALAR Bool
      load --table Terms
      [
      {"_key": "and", "is_stop_word": true}
      ]

      load --table Memos
      [
      {"content": "Hello"},
      {"content": "Hello and Good-bye"},
      {"content": "Good-bye"}
      ]

      select Memos \
        --filter 'query_parallel_or(["content", "content", "content", "content"], \
                  "and", \
                  {"options": {"TokenFilterStopWord.enable": true}})' \
        --match_escalation_threshold -1 \
        --sort_keys -_score

  ストップワードとして登録したキーワードではマッチしてほしくありません。そのため、上記の例では、`match_escalation_threshold`に`-1`を設定しています。エスカレーションが無効でかつ、ストップワードに検索キーワード（`and`）が登録されているため、上記の例では、Groongaは何もレコードを返さないことが期待値です。しかし、この問題が発生すると、Groongaはマッチしたレコードを返却してしまいます。`query_parallel_or()`を使うと、`match_escalation_threshold`が効かないためです。

- 参照ベクターカラムに対する全文検索が動作しない問題を修正しました。

  この問題は、Groonga v14.0.0以降で発生します。また、この問題は、参照ベクターカラムに対して全文検索を実行している場合に影響があります。

  以下の例では、Groongaが`[1, "Linux MySQL"]` と `[2, "MySQL Groonga"]`を返すことが期待ですが、修正前は、以下のように常に0件ヒットになっていました。参照ベクターカラムに対して全文検索しているためです。

      table_create bugs TABLE_PAT_KEY UInt32

      table_create tags TABLE_PAT_KEY ShortText --default_tokenizer TokenDelimit
      column_create tags name COLUMN_SCALAR ShortText

      column_create bugs tags COLUMN_VECTOR tags

      load --table bugs
      [
      ["_key", "tags"],
      [1, "Linux MySQL"],
      [2, "MySQL Groonga"],
      [3, "Mroonga"]
      ]

      column_create tags bugs_tags_index COLUMN_INDEX bugs tags

      select --table bugs --filter 'tags @ "MySQL"'
      [
        [
          0,
          0.0,
          0.0
        ],
        [
          [
            [
              0
            ],
            [
              [
                "_id",
                "UInt32"
              ],
              [
                "_key",
                "UInt32"
              ],
              [
                "tags",
                "tags"
              ]
            ]
          ]
        ]
      ]

## 14.0.3リリース - 2024-05-09

### 改良

- 以下の最適化を行いました。

  - ヒット数が多いときの`OR`検索と`AND`検索のパフォーマンスを向上しました。

  - 前方一致検索(`@^`)のパフォーマンスを向上しました。

  - `A AND B`という条件で、`B`より`A`のレコード数が多い場合の`AND`検索のパフォーマンスを向上しました。

  - 多くの動的カラムを設定している場合の検索パフォーマンスを向上しました。

- [TokenNgram] 新しいオプション`ignore_blank`を追加しました。

  以下のように`TokenBigramIgnoreBlank`を`TokenNgram("ignore_blank", true)`で置き換えることができます。

  `TokenBigram`を使う例です。

      tokenize TokenBigram "! ! !" NormalizerAuto
      [
        [
          0,
          1715155644.64263,
          0.001013517379760742
        ],
        [
          {
            "value": "!",
            "position": 0,
            "force_prefix": false,
            "force_prefix_search": false
          },
          {
            "value": "!",
            "position": 1,
            "force_prefix": false,
            "force_prefix_search": false
          },
          {
            "value": "!",
            "position": 2,
            "force_prefix": false,
            "force_prefix_search": false
          }
        ]
      ]

  `TokenBigramIgnoreBlank`を使う例です。

      tokenize TokenBigramIgnoreBlank "! ! !" NormalizerAuto
      [
        [
          0,
          1715155680.323451,
          0.0009913444519042969
        ],
        [
          {
            "value": "!!!",
            "position": 0,
            "force_prefix": false,
            "force_prefix_search": false
          }
        ]
      ]

  `TokenNgram("ignore_blank", true)`を使う例です。

      tokenize 'TokenNgram("ignore_blank", true)' "! ! !" NormalizerAuto
      [
        [
          0,
          1715155762.340685,
          0.001041412353515625
        ],
        [
          {
            "value": "!!!",
            "position": 0,
            "force_prefix": false,
            "force_prefix_search": false
          }
        ]
      ]

- [Ubuntu] Ubuntu 24.04 LTS (Noble Numbat) をサポートしました。

### 修正

- [request_cancel] `request_cancel`コマンドで実行中のクエリーを中断した時にGroongaがクラッシュすることがある問題を修正しました。

- `--post_filter`使用時に、`--offset`の値が`--post_filter`の結果より大きい場合に予期しないエラーになる問題を修正しました。

  `--filter` と `--offset`の組み合わせで、同様のケースになった場合はエラーは発生しません。`--filter` と `--post-filter`の挙動を合わせました。

      table_create Users TABLE_PAT_KEY ShortText
      column_create Users age COLUMN_SCALAR UInt32
      load --table Users
      [
        ["_key", "age"],
        ["Alice", 21],
        ["Bob", 22],
        ["Chris", 23],
        ["Diana", 24],
        ["Emily", 25]
      ]
      select Users \
        --filter 'age >= 22' \
        --post_filter 'age <= 24' \
        --offset 3 \
        --sort_keys -age --output_pretty yes
      [
        [
          -68,
          1715224057.317582,
          0.001833438873291016,
          "[table][sort] grn_output_range_normalize failed",
          [
            [
              "grn_table_sort",
              "/home/horimoto/Work/free-software/groonga.tag/lib/sort.c",
              1052
            ]
          ]
        ]
      ]

- 近傍フレーズ直積検索で`(...)`内のすべてのフレーズがマッチしない場合に、誤った検索結果を返す場合がある問題を修正しました。

  例えば以下の、`--query '*NPP1"(a) (2)"'`で指定している`(2)`にマッチするレコードはありません。この場合は、何もヒットしないのが正しい挙動ですが、`--query '*NPP1"(a)`相当の挙動になっていました。つまり、`(2)`にマッチするレコードが無いにも関わらず、`ax1`と`axx1`がヒットしていました。

      table_create Entries TABLE_NO_KEY
      column_create Entries content COLUMN_SCALAR Text

      table_create Terms TABLE_PAT_KEY ShortText   --default_tokenizer TokenNgram
      column_create Terms entries_content COLUMN_INDEX|WITH_POSITION Entries content
      load --table Entries
      [
      {"content": "ax1"},
      {"content": "axx1"}
      ]

      select Entries \
        --match_columns content \
        --query '*NPP1"(a) (2)"' \
        --output_columns 'content'
      [
        [
          0,
          1715224211.050228,
          0.001366376876831055
        ],
        [
          [
            [
              2
            ],
            [
              [
                "content",
                "Text"
              ]
            ],
            [
              "ax1"
            ],
            [
              "axx1"
            ]
          ]
        ]
      ]

- `TABLE_HASH_KEY`のテーブルに2^28以上のレコードが存在する時にリハッシュが発生すると、リハッシュが失敗するかテーブル内のデータが壊れる問題を修正しました。

- 以下のケースでハイライト位置がずれる問題を修正しました。

  - 以下のようにハイライト対象の文字の前に全角スペースがある場合。

    `"Groonga　<span class=\"keyword\">高</span>速！"`となることが期待値ですが、以下のように`"Groonga　<span class=\"keyword\">高速</span>！"`となっていました。

        table_create Entries TABLE_NO_KEY
        column_create Entries body COLUMN_SCALAR ShortText

        table_create Terms TABLE_PAT_KEY ShortText \
          --default_tokenizer 'TokenNgram("report_source_location", true)' \
          --normalizer 'NormalizerNFKC150("report_source_offset", true)'
        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, Terms)'
        [
          [
            0,
            1715215640.979517,
            0.001608610153198242
          ],
          [
            [
              [
                1
              ],
              [
                [
                  "highlight_html",
                  null
                ]
              ],
              [
                "Groonga　<span class=\"keyword\">高速</span>！"
              ]
            ]
          ]
        ]

  - `以下のように`TokenNgram("loose_blank", true)`を使っていて、ハイライト対象の文字が全角スペースを含んでいる場合。

    `"<span class=\"keyword\">山田 太郎</span>"`となることが期待値ですが、以下のように`"<span class=\"keyword\">山田 太</span>"`となっていました。

        table_create Entries TABLE_NO_KEY
        column_create Entries body COLUMN_SCALAR ShortText

        table_create Terms TABLE_PAT_KEY ShortText \
          --default_tokenizer 'TokenNgram("loose_blank", true, "report_source_location", true)' \
          --normalizer 'NormalizerNFKC150("report_source_offset", true)'
        column_create Terms document_index COLUMN_INDEX|WITH_POSITION Entries body

        load --table Entries
        [
        {"body": "山田 太郎"}
        ]

        select Entries --output_columns \
          --match_columns body --query '山田太郎' \
          --output_columns 'highlight_html(body, Terms)' --output_pretty yes
        [
          [
            0,
            1715220409.096246,
            0.0004854202270507812
          ],
          [
            [
              [
                1
              ],
              [
                [
                  "highlight_html",
                  null
                ]
              ],
              [
                "<span class=\"keyword\">山田 太</span>"
              ]
            ]
          ]
        ]

  - 以下のようにハイライト対象の文字の先頭に空白スペースがある場合。

    `" <span class=\"keyword\">山</span>田太郎"`となることが期待値ですが、以下のように`" <span class=\"keyword\">山</span>"`となっていました。

        table_create Entries TABLE_NO_KEY
        column_create Entries body COLUMN_SCALAR ShortText

        table_create Terms TABLE_PAT_KEY ShortText \
          --default_tokenizer 'TokenNgram("report_source_location", true)' \
          --normalizer 'NormalizerNFKC150("report_source_offset", true)'
        column_create Terms document_index COLUMN_INDEX|WITH_POSITION Entries body

        load --table Entries
        [
        {"body": " 山田太郎"}
        ]

        select Entries \
          --output_columns \
          --match_columns body \
          --query '山' \
          --output_columns 'highlight_html(body, Terms)' --output_pretty yes
        [
          [
            0,
            1715221627.002193,
            0.001977920532226562
          ],
          [
            [
              [
                1
              ],
              [
                [
                  "highlight_html",
                  null
                ]
              ],
              [
                " <span class=\"keyword\">山</span>"
              ]
            ]
          ]
        ]

  - 以下のようにハイライト対象の２番めの文字が全角スペースの場合。

    `"<span class=\"keyword\">山　田</span>太郎"`となるのが期待値ですが、以下のように`"<span class=\"keyword\">山　田太</span>郎"`となっていました。

        table_create Entries TABLE_NO_KEY
        column_create Entries body COLUMN_SCALAR ShortText

        table_create Terms TABLE_PAT_KEY ShortText \
          --default_tokenizer 'TokenNgram("report_source_location", true)' \
          --normalizer 'NormalizerNFKC150("report_source_offset", true)'
        column_create Terms document_index COLUMN_INDEX|WITH_POSITION Entries body

        load --table Entries
        [
        {"body": "山　田太郎"}
        ]

        select Entries \
          --output_columns \
          --match_columns body \
          --query '山　田' \
          --output_columns 'highlight_html(body, Terms)'
        [
          [
            0,
            1715222501.496007,
            0.0005536079406738281
          ],
          [
            [
              [
                0
              ],
              [
                [
                  "highlight_html",
                  "<span class=\"keyword\">山　田太</span>郎"
                ]
              ]
            ]
          ]
        ]

## 14.0.2リリース - 2024-03-29

### 改良

- 一時テーブルに対して、normalizers/tokenizer/token_filtersを設定したときに出力されるログのログレベルを下げました。

  例えば、この変更の対象のログは以下のようなログです。

      DDL:1234567890:set_normalizers NormalizerAuto

  PGroongaは起動時に一時テーブルに対してノーマライザーを設定するため、このログがノイズになっていました。このログのログレベルは`notice`なので、PGroonga起動時にこのログが出力されてしまうためです。

  そのため、今回のリリースからこのようなログのログレベルを`debug`にしました。これにより、デフォルトでは、PGroonga起動時にこのログが出力されないようになります。

## 14.0.1リリース - 2024-03-14

### 改良

- [load] ノーマライズによって空のキーとなったキーを`load`する時のエラーを止めました。

  `"-"` は、`NormalizerNFKC150("remove_symbol", true)` によって `""` になります。そのため、以下のケースでは"empty key"エラーが報告されます。

      table_create Values TABLE_HASH_KEY ShortText \
        --normalizers 'NormalizerNFKC150("remove_symbol", true)'
      table_create Data TABLE_NO_KEY
      column_create Data value COLUMN_SCALAR Values
      load --table Data
      [
      {"value": "-"}
      ]

  しかし、このようなデータを大量に`load`した場合、多くのエラーログが生成されます。Groongaは空の文字列をインデックスに登録できないため、"empty key"エラーを大量に出力するためです。

  ただ、このようなケースで空の文字列がインデックスへ登録できなくても問題ありません。空の文字列で検索しても何も一致しないためです。そのため、このようなケースの時に"empty key"エラーを報告するのを止めました。

### 修正

- between または、範囲検索時にリクエストキャンセルするとGroongaがクラッシュする問題を修正しました。

  この問題は必ず発生するわけではありません。特定のタイミングでリクエストキャンセルをすると発生します。シーケンシャルサーチなどの検索時間が長い場合に発生しやすいです。

- 以下の条件を満たした時に highlight_html が正しくない結果を返すことがあります。

  - `NormalizerTable` and `NormalizerNFKC150`のように複数のノーマライザーを使っている。

  - 空白を含む文字列をハイライトする。

  例えば、以下のようなケースでこの問題は発生します。

      table_create NormalizationsIndex TABLE_PAT_KEY ShortText --normalizer NormalizerAuto

      table_create Normalizations TABLE_HASH_KEY UInt64
      column_create Normalizations normalized COLUMN_SCALAR LongText
      column_create Normalizations target COLUMN_SCALAR NormalizationsIndex

      column_create NormalizationsIndex index COLUMN_INDEX Normalizations target

      table_create Lexicon TABLE_PAT_KEY ShortText \
        --normalizers 'NormalizerTable("normalized", \
                                       "Normalizations.normalized", \
                                       "target", \
                                       "target"), NormalizerNFKC150'

      table_create Names TABLE_HASH_KEY UInt64
      column_create Names name COLUMN_SCALAR Lexicon

      load --table Names
      [
      ["_key","name"],
      [1,"Sato Toshio"]
      ]

      select Names \
        --query '_key:1 OR name._key:@"Toshio"' \
        --output_columns 'highlight_html(name._key, Lexicon)

      [
        [
          0,
          1710401574.332274,
          0.001911401748657227
        ],
        [
          [
            [
              1
            ],
            [
              [
                "highlight_html",
                null
              ]
            ],
            [
              "sato <span class=\"keyword\">toshi</span>o"
            ]
          ]
        ]
      ]

- [Ubuntu] Ubuntu向けパッケージを提供できるようになりました。

  Groonga 14.0.0では、GroongaのUbuntu向けパッケージを提供していませんでした。Ubuntu向けパッケージのビルド環境の問題で、パッケージを作るのに失敗したためです。

  14.0.1でこの問題を修正したので、今回のリリースからGroongaのUbuntu向けパッケージを提供できるようになりました。

- `clang` を使ってソースからビルドした時にビルドエラーになる問題を修正しました。 [GitHub#1738][Reported by windymelt]

### 感謝

- windymeltさん

## 14.0.0リリース - 2024-02-29

メジャーバージョンアップです! メジャーバージョンアップですが、互換性は壊れていないので、データベースを再構築することなく14.0.0へアップグレードできます。

### 改良

- 新しいトークナイザー`TokenH3Index`を追加しました。（実験的）

  `TokenH3Index`は、`WGS84GetPoint` を `UInt64`(H3 index)に変換します。

- 非テキストベースのトークナイザーを使ったインデックスのオンライン構築とオフライン構築をサポートしました。（実験的）

  `TokenH3Index` は、非テキストベースのトークナイザーの一つです。

- [select] 非テキストベースのトークナイザーを使ったインデックスでの検索をサポートしました。（実験的）.

  `TokenH3Index` は、非テキストベースのトークナイザーの一つです。

- 新しい関数 `distance_cosine()`, `distance_inner_product()`, `distance_l2_norm_squared()`, `distance_l1_norm()` を追加しました。

  これらの関数と`limit N`を使うことで、ベクトル的に距離の近いレコードのみを取得することができます。

  これらの関数は、`output`ステージで距離を計算します。

  ただ、これらの関数はまだ最適化できていません。

  - `distance_cosine()`: コサイン類似度を計算します。

  - `distance_inner_product()`: 内積を計算します。

  - `distance_l2_norm_squared()`: ユークリッド距離を計算します。

  - `distance_l1_norm()`: マンハッタン距離を計算します。

- 新しい関数`number_round()`を追加しました。

- [load] `load`を並列に実行できるようになりました。

  この機能は、`load`の`input_type`が`apache-arrow`の時のみ有効です。

  この機能は、一つのカラムに対し一つのスレッドを割り当てます。対象のカラムがたくさんある時に、ロード時間の短縮が期待できます。

- [select] `--filter`内で配列リテラルをなるべく、uvectorとして使えるようにしました。

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

  すべての要素の型が同じ場合、ベクターの変わりにuvactorを使えます。

- [status] `status`の結果に`n_workers`を追加しました。

- 動的カラムの作成を最適化しました。

- [WAL] 壊れたインデックスの再構築を並列で実行できるようになりました。

- [select] `output_type=apache-arrow`の時に、`_key`が`Int64`型のテーブルへの参照カラムを表示できるようにしました。

### 修正

- [Windows] Windows向けパッケージ内の`groonga-normalizer-mysql`のドキュメントのパスを修正しました。

  今回のリリースから、`groonga-normalizer-mysql`のドキュメントは`share/`以下に格納されます。

- [select] ビットごとの演算を行うとGroongaがクラッシュすることがある問題を修正しました。