BloGroonga

2024-07-04

PostgreSQL用高速日本語全文検索モジュールPGroonga(ぴーじーるんが) 3.2.1リリース

PGroonga 3.2.1をリリースしました!

ハイライト

今回のリリースの主な変更点は下記の通りです。

改良

修正

  • [&@~ operator] 空白のみの条件を含む複数の条件を指定した時にクラッシュする問題を修正しました。

    この問題は、以下のように空白スペースを含む複数のコンディションがある時に発生します。

    CREATE TABLE memos (
      id integer,
      content text
    );
    INSERT INTO memos VALUES (1, 'PostgreSQL is a RDBMS.');
    INSERT INTO memos VALUES (2, 'Groonga is fast full text search engine.');
    INSERT INTO memos VALUES (3, 'PGroonga is a PostgreSQL extension that uses Groonga.');
    CREATE INDEX grnindex ON memos USING pgroonga (content);
    SELECT id, content
      FROM memos
     WHERE content &@~ pgroonga_condition('PGroonga') AND
           content &@~ pgroonga_condition(' ');
    

アップグレード方法

2.0.0以降を使っている場合はアップグレードの「互換性がある場合」用の手順でアップグレードしてください。

1.Y.Zを使っている場合はアップグレードの「非互換の場合」用の手順でアップグレードしてください。 PGroonga 1系と3系は互換性が無いためです。

サポートサービス

PGroongaのサポートサービスを提供しています。インデックスや検索の設計方法に関するコンサルティングやトラブル時の調査、パフォーマンス改善・新機能追加などの技術支援など、PGroongaに関わるサポートが必要な場合はご相談ください。

まとめ

PostgreSQLで高速に日本語全文検索をしたいという方はPGroongaを使ってガンガン検索してください!

2024-07-04

Groonga 14.0.5リリース

Groonga 14.0.5をリリースしました!

それぞれの環境毎のインストール方法: インストール

変更内容

主な変更点は以下の通りです。

改良

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

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

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

修正

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

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

    • OR検索とquery()を組み合わせて使っていること。
    • query()内でAND検索していること。
    • 'A || query("...", "B C")'の順序で条件式が記述されていること。

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

    以下の例では、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
          ]
        ]
      ]
    ]
    
  • [select] --query "A* OR B"のように先に前方一致検索を評価する条件が、誤った検索結果を返すことがある問題を修正しました。

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

    この問題が発生すると、以下の--query "Bo* OR li"という条件が、Boliも前方一致検索として評価されてしまい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"
            ]
          ]
        ]
      ]
    ]
    

おわりに

毎週火曜日の 12:15 - 12:45 にGroonga関連のイベントをオンラインで実施しています。

各イベントの予定はconnpassのページに記載しています。

(上記のページで参加登録しなくても資料やイベントは閲覧可能です。)

今までのオンラインイベントは、以下の場所に格納されていて、いつでも視聴できます!

Groongaリリース自慢会

Groonga開発者に聞け!

興味のある方はぜひ視聴してみてください。 それでは、Mroongaでガンガン検索してください!

2024-05-29

Groonga 14.0.4リリース

Groonga 14.0.4をリリースしました!

それぞれの環境毎のインストール方法: インストール

変更内容

主な変更点は以下の通りです。

修正

  • [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"
            ]
          ]
        ]
      ]
    ]
    
2024-05-09

Groonga 14.0.3リリース

Groonga 14.0.3をリリースしました!

それぞれの環境毎のインストール方法: インストール

変更内容

主な変更点は以下の通りです。

改良

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

    • ヒット数が多いときのOR検索とAND検索のパフォーマンスを向上しました。
    • 前方一致検索(@^)のパフォーマンスを向上しました。
    • A AND Bという条件で、BよりAのレコード数が多い場合のAND検索のパフォーマンスを向上しました。
    • 多くの動的カラムを設定している場合の検索パフォーマンスを向上しました。
  • TokenNgram 新しいオプションignore_blankを追加しました。

    以下のようにTokenBigramIgnoreBlankTokenNgram("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)にマッチするレコードが無いにも関わらず、ax1axx1がヒットしていました。

    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>"
              ]
            ]
          ]
        ]
        
      • 以下のようにハイライト対象の2番めの文字が全角スペースの場合。

        "<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>郎"
                ]
              ]
            ]
          ]
        ]
        
2024-03-29

Groonga 14.0.2リリース

Groonga 14.0.2をリリースしました!

それぞれの環境毎のインストール方法: インストール

変更内容

主な変更点は以下の通りです。

改良

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

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

    DDL:1234567890:set_normalizers NormalizerAuto
    

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

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