BloGroonga

2024-02-29

Groonga 14.0.0リリース

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

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

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

変更内容

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

改良

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

    TokenH3Indexは、WGS84GetPointUInt64(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を並列に実行できるようになりました。

    この機能は、loadinput_typeapache-arrowの時のみ有効です。

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

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

    uvectorは、要素が固定長サイズのベクターです。 すべての要素の型が同じ場合、ベクターの変わりにuvactorを使えます。

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

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

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

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

修正

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

    Documents of groonga-normalizer-mysql put under the share/ in this release.

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

2024-01-10

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

PostgreSQLで高速日本語全文検索をできるようにするPGroongaの3.1.6をリリースしました!

ハイライト

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

改良

  • 新しいオプション pgroonga.enable_row_level_security を追加しました。

    PGroongaのRLS(Row level security)サポートの有効/無効を設定できます。デフォルト値は有効です。 PGroongaのRLSサポートを無効にすることでパフォーマンスが向上するかもしれません。 しかし、PostgreSQLのRLS機能を使っている環境ではPGroongaのRLSサポートを無効にしてはいけません。無効にするとセキュリティーのリスクがあります。

    したがって、このオプションを使ってPGroongaのRLSサポートを無効にする場合は、事前にPostgreSQLのRLS機能を使っていないことを十分に確認してください。

    特定のセッションで一時的に設定をする場合は、下記のSQLで有効/無効を切り替えられます。

    • RLSサポートを無効にする場合

      SET pgroonga.enable_row_level_security = off
      
    • RLSサポートを有効にする場合

      SET pgroonga.enable_row_level_security = on
      

      設定を永続化する場合は、PostgreSQLの設定ファイルに以下のように記載してください。

    • RLSサポートを無効にする場合

      pgroonga.enable_row_level_security = off
      
    • RLSサポートを有効にする場合

      pgroonga.enable_row_level_security = on
      
  • 新しい型 pgroonga_condition を追加しました。関連して、新しい関数 pgroonga_condition() を追加しました。

    pgroonga_full_text_search_condition 型と pgroonga_full_text_search_condition_with_scorers 型は非推奨になります。 上記の型の代わりに、 pgroonga_condition を使ってください。

    pgroonga_full_text_search_condition 型と pgroonga_full_text_search_condition_with_scorers 型を使った クエリーは以下のように変化します。

    (変更前):

    column &@~ ('query', weights, 'scorers', index_name)::pgroonga_full_text_search_condition_with_scorers
    column &@~ ('query', weights, index_name)::pgroonga_full_text_search_condition
    

    (変更後):

    column &@~ pgroonga_conditon('query', weights, 'scorers', index_name => 'index_name')
    column &@~ pgroonga_conditon('query', weights, index_name => 'index_name')
    

    'index_name' は、index_name => 'index_name' のように 引数名 => '値' の形式で指定する必要があることに注意してください。 なぜ、 'index_name' をこのように指定しなければならないのかを解説します。

    pgroonga_condition() のシグネチャーは以下の通りで、指定が不要な引数は省略可能です。 引数を省略すると、どの位置になんの引数があるのかがわからなくなります。そのため、以下のシグネチャーと引数の位置が異なるものについては 引数名 => '値' の形式で書くことで、なんの引数の値なのかを指定します。

      pgroonga_condition(query text,
                         weights int[],
                         scorers text[],
                         schema_name text,
                         index_name text,
                         column_name text)
    
  • [開発者向け] ビルド環境をセットアップするスクリプトを新しく追加しました。 [GitHub#358][askdkcさんがパッチ提供]

    以下のように使用します。 Debian/Ubuntu環境で動作します。AlmaLinuxなどのRed Hat Enterprise Linux派生のディストリビューションでは動作しません。

      $ git clone https://github.com/pgroonga/pgroonga.git
      $ cd pgroonga
      $ ./setup.sh #PGroongaをビルドする環境を作ります。
      $ ./build.sh SOURCE_DIRECTORY BUILD_DIRECTORY #PGroongaをビルドします。
    

修正

  • PGroongaを2.4.1から2.4.2へバージョンアップすると、 pgroonga_snippet_html() が使えなくなる問題を修正しました。[takadatさんの報告]

  • pgroonga_query_expand() の第一引数にPostgreSQLの通常のテーブル以外を指定すると、PGroongaがクラッシュする問題を修正しました。

    例えば、以下のように pgroonga_query_expand() の第一引数に外部テーブルを指定すると、PGroongaはクラッシュします。

    CREATE EXTENSION IF NOT EXISTS postgres_fdw;
    
    CREATE SERVER remote_server
        FOREIGN DATA WRAPPER postgres_fdw
        OPTIONS (host 'localhost', port '5432', dbname 'remote_database');
    
    CREATE FOREIGN TABLE synonym_groups (
      synonyms text[]
    ) SERVER remote_server;
    
    SELECT pgroonga_query_expand('synonym_groups',
                                 'synonyms',
                                 'synonyms',
                                 'groonga');
    
    server closed the connection unexpectedly
    	This probably means the server terminated abnormally
    	before or while processing the request.
    The connection to the server was lost. Attempting reset: Failed.
    
  • PGroonga内で多くのエラーが発生した場合、エラー情報を記録するスタックを使い果たしてPostgreSQLがPANICを起こす問題を修正しました。

    この問題は、PGroonga 2.3.3以降で発生します。

感謝

  • askdkcさん
  • takadatさん

アップグレード方法

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

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

サポートサービス

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

まとめ

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

2024-01-09

Groonga 13.1.1リリース

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

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

変更内容

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

改良

  • MinGW32 でビルドしているWindowsパッケージのサポートをやめました。 [GitHub#1654]

  • --match_columns--query の組み合わせで vector_column[N] OPERATOR literal をサポートしました。

    --filter では以前から vector_column[N] OPERATOR literal でベクターカラムの特定の特定の要素にマッチさせることができましたが 今回のリリースで --match_columns--query の組み合わせでもできるようになりました。

修正

  • [Windows] groonga-normalizer-mysql をバンドルしました。 [GitHub#1655]

    Windows版のGroonga 13.1.0に groonga-normalizer-mysql が含まれていませんでした。 この問題はGroonga13.1.0でのみ発生します。

2023-12-26

Groonga 13.1.0リリース

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

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

変更内容

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

改良

  • [select] トレースログもキャッシュするようにしました。

  • Apache Arrow フォーマットの応答で dict<string> の出力をサポートしました。

  • [Groonga HTTPサーバー] 新しい content type application/vnd.apache.arrow.stream をサポートしました。

  • [query] 以下のような空の入力をサポートしました。

    table_create Users TABLE_NO_KEY
    column_create Users name COLUMN_SCALAR ShortText
    
    table_create Lexicon TABLE_HASH_KEY ShortText   --default_tokenizer TokenBigramSplitSymbolAlphaDigit   --normalizer NormalizerAuto
    column_create Lexicon users_name COLUMN_INDEX|WITH_POSITION Users name
    load --table Users
    [
    {"name": "Alice"},
    {"name": "Alisa"},
    {"name": "Bob"}
    ]
    
    select Users   --output_columns name,_score   --filter 'query("name", "  	")'
    [
      [
        0,
        0.0,
        0.0
      ],
      [
        [
          [
            0
          ],
          [
            [
              "name",
              "ShortText"
            ],
            [
              "_score",
              "Int32"
            ]
          ]
        ]
      ]
    ]
    
  • BFloat16をサポートしました。(実験的)

    BFloat16のloadとselectができるだけです。 bfloat16_value - 1.2 のような算術演算はできません。

  • [column_create] 新しいフラグ WEIGHT_BFLOAT16 を追加しました。

修正

  • [select] Groonga が output_pretty=yes の結果をキャッシュした場合、 output_pretty をつけていないクエリーであっても、 output_pretty をつけて返してしまう問題を修正しました。

  • 誤ったデータを作り出してしまう問題を修正しました。

    通常、ユーザーはこれを明示的に実行できません。 数値の動的カラムや一時結果セットが作られたとき、あるいは使われているとき、かつ クエリーに OR を使っている場合に内部的に発生することがあります。

    例えば、以下のクエリーで誤ったデータを作り出すことがあります。

    select TABLE \
      --match_columns TEXT_COLUMN \
      --query 'A B OR C' \
      --columns[NUMERIC_DYNAMIC_COLUMN].stage result_set \
      --columns[NUMERIC_DYNAMIC_COLUMN].type Float32 \
      --columns[NUMERIC_DYNAMIC_COLUMN].flags COLUMN_VECTOR
    

    もしこの問題が起こった場合は、 NUMERIC_DYNAMIC_COLUMN は多くのごみ要素を含んでいます。そして、それは多くのメモリー消費の原因にもなります。

    この問題はスタック上の未初期化の変数が原因です。そのため、発生するかもしれないし、しないかもしれないことに注意してください。

  • 有効な normalizers/token_filters の設定が失敗することがある問題を修正しました。

  • [fuzzy_search] 以下の3つの条件が成立した時にクラッシュする問題を修正しました。

    1. クエリーが2つまたはそれ以上のマルチバイト文字を持っている場合。

    2. ${ASCII}${ASCII}${MULTIBYTE}* という形の文字列がパトリシアトライのテーブルにある場合。

    3. WITH_TRANSPOSITION が有効な場合。

    例えば、以下のようにパトリシアトライのテーブル内にある"aaあ"とクエリー"あiう"のペアは問題を起こします。

    table_create Users TABLE_NO_KEY
    column_create Users name COLUMN_SCALAR ShortText
    
    table_create Names TABLE_PAT_KEY ShortText
    column_create Names user COLUMN_INDEX Users name
    load --table Users
    [
    {"name": "aaあ"},
    {"name": "あうi"},
    {"name": "あう"},
    {"name": "あi"},
    {"name": "iう"}
    ]
    select Users \
      --filter 'fuzzy_search(name, "あiう", {"with_transposition": true, "max_distance": 3})' \
      --output_columns 'name, _score' \
      --match_escalation_threshold -1
    
2023-10-31

Groonga 13.0.9リリース

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

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

変更内容

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

改良

  • [select] --fuzzy_max_expansions のデフォルト値を0から10に変更しました。

    --fuzzy_max_expansions を使うことで検索に使う編集距離の近い語の数を制限できます。 この引数はヒット数と検索パフォーマンスのバランスを取るための引数です。(編集距離の近い語が多すぎると検索速度が遅くなるため、上限を設定できるようにして検索が遅くなりすぎないようにできます。)

    --fuzzy_max_expansions のデフォルト値は0でしたが、 0の場合は語彙表にある編集距離が --fuzzy_max_distance 以下の語すべてを使って検索するため、この引数をそのまま使うと検索が遅くなるケースが出てきてしまいます。そのため、今回のリリースから --fuzzy_max_distance のデフォルト値を0から10に変更しました。

  • [select] select コマンドの引数に新しく --fuzzy_with_transposition を追加しました。(実験的)

    「隣接する文字の交換」の編集距離はデフォルトでは1ですが、この引数を使うことで「隣接する文字の交換」の編集距離を1または2に指定できます。

    --fuzzy_with_transpositionyes の場合、文字の交換の編集距離は 1 になります。 それ以外の値が指定された場合は、「隣接する文字の交換」の編集距離が2になります。

    通常のユースケースでは、 --fuzzy_with_transposition を操作する必要はありません。

  • [select] select の引数に新しく --fuzzy_tokenize を追加しました。(実験的)

    --fuzzy_tokenizeyes の時、Groongaは誤字を許容する検索で --default_tokenizer で指定したトークナイザーを使います。 --fuzzy_tokenize のデフォルト値は no です。--fuzzy_tokenize が有用なケースは、以下のケースです。

    誤字を許容する検索では、検索キーワードをどのようにトークナイズするは重要なポイントの1つです。 アルファベット等のASCII文字は、"Thjs is a pen" なら "Thjs", "is", "a", "pen" と分割されるので、"Thjs"を "This"として検索することができます。 ただ、日本語はスペース区切りの言語ではないため、デフォルトのトークナイザーでは、意味のある塊に検索キーワードを分割できません。 日本語の場合は、日本語に特化したトークナイザーを指定したくなります。 --fuzzy_tokenize はこのように、検索対象の言語によってトークナイザーを変更するための引数です。

    検索対象が日本語のデータのみの場合は、 --default_tokenizerTokenMecab を指定することで、日本語でも誤字を許容した検索が可能になります。

  • [ノーマライザー] NormalizerNFKC* に新しく remove_blank_force オプションを追加しました。

    remove_blank_forcefalse の時は、以下のようにノーマライザーは空白を無視しません。

    table_create Entries TABLE_NO_KEY
    column_create Entries body COLUMN_SCALAR ShortText
    
    load --table Entries
    [
    {"body": "Groonga はとても速い"},
    {"body": "Groongaはとても速い"}
    ]
    
    select Entries --output_columns \
      'highlight(body, \
        "gaはとても", "<keyword>", "</keyword>", \
        {"normalizers": "NormalizerNFKC150(\\"remove_blank_force\\", false)"} \
      )'
    [
      [
        0,
        0.0,
        0.0
      ],
      [
        [
          [
            2
          ],
          [
            [
              "highlight",
              null
            ]
          ],
          [
            "Groonga はとても速い"
          ],
          [
            "Groon<keyword>gaはとても</keyword>速い"
          ]
        ]
      ]
    ]
    
  • [select] select コマンドの引数に新しく --output_trace_log を追加しました。(実験的)

    --output_trace_logyes を指定し --command_version 3 を指定した場合、Groongaは以下のようなログを新規に出力します。

    table_create Memos TABLE_NO_KEY
    column_create Memos content COLUMN_SCALAR ShortText
    
    table_create Lexicon TABLE_PAT_KEY ShortText   --default_tokenizer TokenNgram   --normalizer NormalizerNFKC150
    column_create Lexicon memos_content   COLUMN_INDEX|WITH_POSITION Memos content
    
    load --table Memos
    [
    {"content": "This is a pen"},
    {"content": "That is a pen"},
    {"content": "They are pens"}
    ]
    
    select Memos \
      --match_columns content \
      --query "Thas OR ere" \
      --fuzzy_max_distance 1 \
      --output_columns *,_score \
      --command_version 3 \
      --output_trace_log yes \
    --output_type apache-arrow
    
    return_code: int32
    start_time: timestamp[ns]
    elapsed_time: double
    error_message: string
    error_file: string
    error_line: uint32
    error_function: string
    error_input_file: string
    error_input_line: int32
    error_input_command: string
    -- metadata --
    GROONGA:data_type: metadata
    	return_code	               start_time	elapsed_time	error_message	error_file	error_line	error_function	error_input_file	error_input_line	error_input_command
    0	          0	1970-01-01T09:00:00+09:00	    0.000000	       (null)	    (null)	    (null)	        (null)	          (null)	          (null)	             (null)
    ========================================
    depth: uint16
    sequence: uint16
    name: string
    value: dense_union<0: uint32=0, 1: string=1>
    elapsed_time: uint64
    -- metadata --
    GROONGA:data_type: trace_log
    	depth	sequence	name	value	elapsed_time
     0	    1	       0	ii.select.input	Thas 	           0
     1	    2	       0	ii.select.exact.n_hits	    0	           1
     2	    2	       0	ii.select.fuzzy.input	Thas 	           2
     3	    2	       1	ii.select.fuzzy.input.actual	that 	           3
     4	    2	       2	ii.select.fuzzy.input.actual	this 	           4
     5	    2	       3	ii.select.fuzzy.n_hits	    2	           5
     6	    1	       1	ii.select.n_hits	    2	           6
     7	    1	       0	ii.select.input	ere  	           7
     8	    2	       0	ii.select.exact.n_hits	    2	           8
     9	    1	       1	ii.select.n_hits	    2	           9
    ========================================
    content: string
    _score: double
    -- metadata --
    GROONGA:n_hits: 2
    	content	    _score
    0	This is a pen	  1.000000
    1	That is a pen	  1.000000
    

    --output_trace_log は、コマンドバージョン3でのみ有効です。

    以下のケースで有用です。:

    • 誤字を許容する検索で使われた実際のキーワードの検知。
    • クエリーログを見ずに実行時間を測定。
  • [snippet] normalizers オプションをサポートしました。

    オプション付きのノーマライザーが使えるようになります。例えば、以下のように snippet() 関数内でスペースを無視したくない時にこのオプションを使います。

    table_create Entries TABLE_NO_KEY
    column_create Entries content COLUMN_SCALAR ShortText
    
    load --table Entries
    [
    {"content": "Groonga and MySQL"},
    {"content": "Groonga and My SQL"}
    ]
    
    select Entries \
      --output_columns \
        '   snippet(content,   "MySQL", "<keyword>", "</keyword>",   {"normalizers": "NormalizerNFKC150(\\"remove_blank_force\\", false)"}   )'
    [
      [
        0,
        0.0,
        0.0
      ],
      [
        [
          [
            2
          ],
          [
            [
              "snippet",
              null
            ]
          ],
          [
            [
              "Groonga and <keyword>MySQL</keyword>"
            ]
          ],
          [
            null
          ]
        ]
      ]
    ]
    

修正

  • Time OPERATOR Float{,32} が正しく評価されない問題を修正しました。 GH-1624[Reported by yssrku]

    Float{,32} 内のマイクロ秒(秒未満の小さい値)が使えていませんでした。この問題は Time OPERATOR Float{,32} の時だけ発生します。 以下のように、 load --ifexists 'A OP B || C OP D' でこの問題は発生します。

    table_create Reports TABLE_HASH_KEY ShortText
    column_create Reports content COLUMN_SCALAR Text
    column_create Reports modified_at COLUMN_SCALAR Time
    
    load --table Reports
    [
    {"_key": "a", "content": "", "modified_at": 1663989875.438}
    ]
    
    load \
      --table Reports \
      --ifexists 'content == "" && modified_at <= 1663989875.437'
    

    しかし、 select --filter では発生しません。

  • alnum(a-zA-Z0-9) + blank が検知されることがある問題を修正しました。

    この問題が発生すると以下のように highlight() で意図しない結果になります。

    table_create Entries TABLE_NO_KEY
    column_create Entries body COLUMN_SCALAR ShortText
    
    load --table Entries
    [
    {"body": "Groonga is fast"}
    ]
    
    select Entries \
      --output_columns 'highlight(body, "ai", "<keyword>", "</keyword>")'
    
    [
      [
        0,0.0,0.0
      ],
      [
        [
          [
            1
          ],
          [
            [
              "highlight",
              null
            ]
          ],
          [
            "Groong<keyword>a i</keyword>s fast"
          ]
        ]
      ]
    ]
    

    しかし、上記の結果は期待していない結果です。上記ケースでは a i は検知してほしくありません。