Skip to main content
`Ctrl`+`K`

# お知らせ

## 13.0.2リリース - 2023-07-12

### 改良

- [Ubuntu] Ubuntu 18.04（Bionic Beaver）のサポートをやめました。

- [Ubuntu] Ubuntu 23.04（Lunar Lobster）をサポートしました。

- [Debian GNU/Linux] Debian 12 (bookworm) をサポートしました。

- [Oracle Linux] Oracle Linuxサポートをやめました。代わりに AlmaLinux 用パッケージを使ってください。

- [`grn_highlighter`] タグの変更をサポートしました。

  [GH-1453] [askdkcさんが報告]

- [`grn_highlighter`] ノーマライザーの変更をサポートしました。

- [`grn_highlighter`] HTMLモードの変更をサポートしました。

- [`grn_highlighter`] 複数タグをサポートしました。

- [highlight] `sequential_class_tag_mode` オプションを追加しました。

- [highlight_html] `sequential_class_tag_mode` オプションを追加しました。

- [reference_acquire] `--recursive dependent` が使われたときに対象オブジェクト用のインデックスカラムも参照するように変更しました。

  対象オブジェクトがカラムの場合、そのカラム用のインデックスカラムも参照されます。

  対象オブジェクトがテーブルの場合、そのテーブル用のインデックスカラムも参照されます。

  対象オブジェクトがDBの場合、すべてのテーブルが対象オブジェクトになります。

- [CMake] CMake 3.16以降を必須としました。近い将来、GNU AutotoolsではなくCMakeを推奨ビルドツールとし、いずれGNU Autotoolsサポートをやめる予定です。

- [CMake] CMakeパッケージに対応しました。 `find_package(Groonga)` というように使えます。

- [Packaging] ソースアーカイブ中の `configure` を生成しているGNU Autotoolsを更新しました。

  [ranguba/rroonga#220] [ZangRuochenさんが報告]

- [reference_acquire] 組み込みオブジェクト用のリファレンスカウント実装を最適化しました。

- `SIGABRT` 発生時もバックトレースのログ出力するようにしました。

### 修正

- [順序付き近傍フレーズ直積検索条件] [順序付き近傍フレーズ直積検索演算子] マッチするべきレコードがマッチしないことがある問題を修正しました。

  この問題は、クエリー内に3つ以上トークンがあり、かつ、それらがオーバーラップしているときに発生します。たとえば、 `abc` と `abcd` はうまく動かない組み合わせです。もし、短い方（ `abc` ）が長い方（ `abcd` ）より前にある場合はこの問題は発生しません。たとえば、 `ONPP1 "(abcd abc) (1 2)"` は動きますが、 `ONPP1 "(abc abcd) (1 2)"` は動きません。

- 複数の重み調整演算子を使った場合、不正な重みが使われることがある問題を修正しました。

- [クエリー構文] 誤字を修正しました。

  [GH-1560] [Dylan Golowさんがパッチ提供]

- [近傍フレーズ検索条件] [近傍フレーズ検索演算子] [近傍フレーズ直積検索条件] [近傍フレーズ直積検索演算子] [順序付き近傍フレーズ検索条件] [順序付き近傍フレーズ検索演算子] [順序付き近傍フレーズ直積検索条件] [順序付き近傍フレーズ直積検索演算子] `additional_last_interval` を使っている場合、距離の計算が間違っている問題を修正しました。

  たとえば、 `aaaxxxbbbcdefghi.` に対して `*NP3,-1"aaa bbb .$"` で検索するケースを考えます。このケースでは `aaa` と `bbb` の間のトークン数は3であるべきですが7になっていました。

- [近傍フレーズ直積検索条件] [近傍フレーズ直積検索演算子] [順序付き近傍フレーズ直積検索条件] [順序付き近傍フレーズ直積検索演算子] 同じフレーズグループ内に同じフレーズが存在するときに無限ループする問題を修正しました。

  たとえば、 `*NPP1 "(abcd abc abcd bcde) (efghi)"` は問題が発生するクエリーです。なぜなら最初のフレーズグループ内に2つ `abcd` が存在するからです。

  たとえば、 `*NPP1 "(abcde \"abc de\") (efghi)"` は問題が発生するクエリーです。なぜなら最初のフレーズグループ内に `abcde` と `"abc de"` が存在するからです。これらは「論理的に」同じフレーズです。

- ロック獲得に失敗した場合に内部のロックカウントを減らしていない問題を修正しました。通常はこれが問題になることはありません。

### 感謝

- askdkcさん

- Dylan Golowさん

- ZangRuochenさん

## 13.0.1リリース - 2023-03-24

### 改良

- [highlight_html] 前方一致検索をサポートしました。

  `highlight_html` で前方一致検索ができるようになりました。

  ただし、ハイライトするキーワードは、最初の出現箇所だけでなく、途中および最後の出現箇所もハイライトされます。

      table_create Tags TABLE_NO_KEY
      column_create Tags name COLUMN_SCALAR ShortText

      table_create Terms TABLE_PAT_KEY ShortText \
        --normalizer 'NormalizerNFKC150'
      column_create Terms tags_name COLUMN_INDEX Tags name

      load --table Tags
      [
      {"name": "Groonga"}
      ]

      select Tags \
        --query "name:^g" \
        --output_columns "highlight_html(name)"
      #[
      #  [
      #    0,
      #    0.0,
      #    0.0
      #  ],
      #  [
      #    [
      #      [
      #        1
      #      ],
      #      [
      #        [
      #          "highlight_html",
      #          null
      #        ]
      #      ],
      #      [
      #        "<span class=\"keyword\">G</span>roon<span class=\"keyword\">g</span>a"
      #      ]
      #    ]
      #  ]
      #]

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

  - `unify_kana_prolonged_sound_mark`

    このオプションによって、長音記号を以下のように正規化できます。

        ァー -> ァア, アー -> アア, ヵー -> ヵア, カー -> カア, ガー -> ガア, サー -> サア, ザー -> ザア,
        ター -> タア, ダー -> ダア, ナー -> ナア, ハー -> ハア, バー -> バア, パー -> パア, マー -> マア,
        ャー -> ャア, ヤー -> ヤア, ラー -> ラア, ヮー -> ヮア, ワー -> ワア, ヷー -> ヷア,

        ィー -> ィイ, イー -> イイ, キー -> キイ, ギー -> ギイ, シー -> シイ, ジー -> ジイ, チー -> チイ,
        ヂー -> ヂイ, ニー -> ニイ, ヒー -> ヒイ, ビー -> ビイ, ピー -> ピイ, ミー -> ミイ, リー -> リイ,
        ヰー -> ヰイ, ヸー -> ヸイ,

        ゥー -> ゥウ, ウー -> ウウ, クー -> クウ, グー -> グウ, スー -> スウ, ズー -> ズウ, ツー -> ツウ,
        ヅー -> ヅウ, ヌー -> ヌウ, フー -> フウ, ブー -> ブウ, プー -> プウ, ムー -> ムウ, ュー -> ュウ,
        ユー -> ユウ, ルー -> ルウ, ヱー -> ヱウ, ヴー -> ヴウ,

        ェー -> ェエ, エー -> エエ, ヶー -> ヶエ, ケー -> ケエ, ゲー -> ゲエ, セー -> セエ, ゼー -> ゼエ,
        テー -> テエ, デー -> デエ, ネー -> ネエ, ヘー -> ヘエ, ベー -> ベエ, ペー -> ペエ, メー -> メエ,
        レー -> レエ, ヹー -> ヹエ,

        ォー -> ォオ, オー -> オオ, コー -> コオ, ゴー -> ゴオ, ソー -> ソオ, ゾー -> ゾオ, トー -> トオ,
        ドー -> ドオ, ノー -> ノオ, ホー -> ホオ, ボー -> ボオ, ポー -> ポオ, モー -> モオ, ョー -> ョオ,
        ヨー -> ヨオ, ロー -> ロオ, ヲー -> ヲオ, ヺー -> ヺオ,

        ンー -> ンン

        ぁー -> ぁあ, あー -> ああ, ゕー -> ゕあ, かー -> かあ, がー -> があ, さー -> さあ, ざー -> ざあ,
        たー -> たあ, だー -> だあ, なー -> なあ, はー -> はあ, ばー -> ばあ, ぱー -> ぱあ, まー -> まあ,
        ゃー -> ゃあ, やー -> やあ, らー -> らあ, ゎー -> ゎあ, わー -> わあ

        ぃー -> ぃい, いー -> いい, きー -> きい, ぎー -> ぎい, しー -> しい, じー -> じい, ちー -> ちい,
        ぢー -> ぢい, にー -> にい, ひー -> ひい, びー -> びい, ぴー -> ぴい, みー -> みい, りー -> りい,
        ゐー -> ゐい

        ぅー -> ぅう, うー -> うう, くー -> くう, ぐー -> ぐう, すー -> すう, ずー -> ずう, つー -> つう,
        づー -> づう, ぬー -> ぬう, ふー -> ふう, ぶー -> ぶう, ぷー -> ぷう, むー -> むう, ゅー -> ゅう,
        ゆー -> ゆう, るー -> るう, ゑー -> ゑう, ゔー -> ゔう

        ぇー -> ぇえ, えー -> ええ, ゖー -> ゖえ, けー -> けえ, げー -> げえ, せー -> せえ, ぜー -> ぜえ,
        てー -> てえ, でー -> でえ, ねー -> ねえ, へー -> へえ, べー -> べえ, ぺー -> ぺえ, めー -> めえ,
        れー -> れえ

        ぉー -> ぉお, おー -> おお, こー -> こお, ごー -> ごお, そー -> そお, ぞー -> ぞお, とー -> とお,
        どー -> どお, のー -> のお, ほー -> ほお, ぼー -> ぼお, ぽー -> ぽお, もー -> もお, ょー -> ょお,
        よー -> よお, ろー -> ろお, をー -> をお

        んー -> んん

    以下は、 `unify_kana_prolonged_sound_mark` オプションの使用例です。

        table_create --name Animals --flags TABLE_HASH_KEY --key_type ShortText
        column_create --table Animals --name name --type ShortText
        column_create --table Animals --name sound --type ShortText
        load --table Animals
        [
        {"_key":"1","name":"羊", "sound":"メーメー"},
        ]

        table_create \
          --name idx_animals_sound \
          --flags TABLE_PAT_KEY \
          --key_type ShortText \
          --default_tokenizer TokenBigram \
          --normalizer 'NormalizerNFKC150("unify_kana_prolonged_sound_mark", true)'
        column_create --table idx_animals_sound --name animals_sound --flags COLUMN_INDEX|WITH_POSITION --type Animals --source sound

        select --table Animals --query sound:@メエメエ
        #[
        #  [
        #    0,
        #    1677829950.652696,
        #    0.01971983909606934
        #  ],
        #  [
        #    [
        #      [
        #        1
        #      ],
        #      [
        #        [
        #          "_id",
        #          "UInt32"
        #        ],
        #        [
        #          "_key",
        #          "ShortText"
        #        ],
        #        [
        #          "name",
        #          "ShortText"
        #        ],
        #        [
        #          "sound",
        #          "ShortText"
        #        ]
        #      ],
        #      [
        #        1,
        #        "1",
        #        "羊",
        #        "メーメー"
        #      ]
        #    ]
        #  ]
        #]

  - `unify_kana_hyphen`

    このオプションを使うことで、ハイフンを以下のように正規化できます。

        ァ- -> ァア, ア- -> アア, ヵ- -> ヵア, カ- -> カア, ガ- -> ガア, サ- -> サア, ザ- -> ザア,
        タ- -> タア, ダ- -> ダア, ナ- -> ナア, ハ- -> ハア, バ- -> バア, パ- -> パア, マ- -> マア,
        ャ- -> ャア, ヤ- -> ヤア, ラ- -> ラア, ヮ- -> ヮア, ワ- -> ワア, ヷ- -> ヷア,

        ィ- -> ィイ, イ- -> イイ, キ- -> キイ, ギ- -> ギイ, シ- -> シイ, ジ- -> ジイ, チ- -> チイ,
        ヂ- -> ヂイ, ニ- -> ニイ, ヒ- -> ヒイ, ビ- -> ビイ, ピ- -> ピイ, ミ- -> ミイ, リ- -> リイ,
        ヰ- -> ヰイ, ヸ- -> ヸイ,

        ゥ- -> ゥウ, ウ- -> ウウ, ク- -> クウ, グ- -> グウ, ス- -> スウ, ズ- -> ズウ, ツ- -> ツウ,
        ヅ- -> ヅウ, ヌ- -> ヌウ, フ- -> フウ, ブ- -> ブウ, プ- -> プウ, ム- -> ムウ, ュ- -> ュウ,
        ユ- -> ユウ, ル- -> ルウ, ヱ- -> ヱウ, ヴ- -> ヴウ,

        ェ- -> ェエ, エ- -> エエ, ヶ- -> ヶエ, ケ- -> ケエ, ゲ- -> ゲエ, セ- -> セエ, ゼ- -> ゼエ,
        テ- -> テエ, デ- -> デエ, ネ- -> ネエ, ヘ- -> ヘエ, ベ- -> ベエ, ペ- -> ペエ, メ- -> メエ,
        レ- -> レエ, ヹ- -> ヹエ,

        ォ- -> ォオ, オ- -> オオ, コ- -> コオ, ゴ- -> ゴオ, ソ- -> ソオ, ゾ- -> ゾオ, ト- -> トオ,
        ド- -> ドオ, ノ- -> ノオ, ホ- -> ホオ, ボ- -> ボオ, ポ- -> ポオ, モ- -> モオ, ョ- -> ョオ,
        ヨ- -> ヨオ, ロ- -> ロオ, ヲ- -> ヲオ, ヺ- -> ヺオ,

        ン- -> ンン

        ぁ- -> ぁあ, あ- -> ああ, ゕ- -> ゕあ, か- -> かあ, が- -> があ, さ- -> さあ, ざ- -> ざあ,
        た- -> たあ, だ- -> だあ, な- -> なあ, は- -> はあ, ば- -> ばあ, ぱ- -> ぱあ, ま- -> まあ,
        ゃ- -> ゃあ, や- -> やあ, ら- -> らあ, ゎ- -> ゎあ, わ- -> わあ

        ぃ- -> ぃい, い- -> いい, き- -> きい, ぎ- -> ぎい, し- -> しい, じ- -> じい, ち- -> ちい,
        ぢ- -> ぢい, に- -> にい, ひ- -> ひい, び- -> びい, ぴ- -> ぴい, み- -> みい, り- -> りい,
        ゐ- -> ゐい

        ぅ- -> ぅう, う- -> うう, く- -> くう, ぐ- -> ぐう, す- -> すう, ず- -> ずう, つ- -> つう,
        づ- -> づう, ぬ- -> ぬう, ふ- -> ふう, ぶ- -> ぶう, ぷ- -> ぷう, む- -> むう, ゅ- -> ゅう,
        ゆ- -> ゆう, る- -> るう, ゑ- -> ゑう, ゔ- -> ゔう

        ぇ- -> ぇえ, え- -> ええ, ゖ- -> ゖえ, け- -> けえ, げ- -> げえ, せ- -> せえ, ぜ- -> ぜえ,
        て- -> てえ, で- -> でえ, ね- -> ねえ, へ- -> へえ, べ- -> べえ, ぺ- -> ぺえ, め- -> めえ,
        れ- -> れえ

        ぉ- -> ぉお, お- -> おお, こ- -> こお, ご- -> ごお, そ- -> そお, ぞ- -> ぞお, と- -> とお,
        ど- -> どお, の- -> のお, ほ- -> ほお, ぼ- -> ぼお, ぽ- -> ぽお, も- -> もお, ょ- -> ょお,
        よ- -> よお, ろ- -> ろお, を- -> をお

        ん- -> んん

    以下は、 `unify_kana_hyphen` オプションの使用例です。

        table_create --name Animals --flags TABLE_HASH_KEY --key_type ShortText
        column_create --table Animals --name name --type ShortText
        column_create --table Animals --name sound --type ShortText
        load --table Animals
        [
        {"_key":"1","name":"羊", "sound":"メ-メ-"},
        ]

        table_create \
          --name idx_animals_sound \
          --flags TABLE_PAT_KEY \
          --key_type ShortText \
          --default_tokenizer TokenBigram \
          --normalizer 'NormalizerNFKC150("unify_kana_hyphen", true)'
        column_create --table idx_animals_sound --name animals_sound --flags COLUMN_INDEX|WITH_POSITION --type Animals --source sound

        select --table Animals --query sound:@メエメエ
        #[
        #  [
        #    0,1677829950.652696,
        #    0.01971983909606934
        #  ],
        #  [
        #    [
        #      [
        #        1
        #      ],
        #      [
        #        [
        #          "_id",
        #          "UInt32"
        #        ],
        #        [
        #          "_key",
        #          "ShortText"
        #        ],
        #        [
        #          "name",
        #          "ShortText"
        #        ],
        #        [
        #          "sound",
        #          "ShortText"
        #        ]
        #      ],
        #      [
        #        1,
        #        "1",
        #        "羊",
        #        "メ-メ-"
        #      ]
        #    ]
        #  ]
        #]

- [近傍検索条件][近傍検索演算子] 各近傍検索に `${MIN_INTERVAL}` オプションを追加しました。

  `${MIN_INTERVAL}` でフレーズ間（単語間）の最低距離を指定できるようになりました。フレーズ間（単語間）の距離は、最低でもこの値以上である必要があります。

  新しい構文は以下のとおりです。

      *N${MAX_INTERVAL},${MAX_TOKEN_INTERVAL_1}|${MAX_TOKEN_INTERVAL_2}|...,${MIN_INTERVAL} "word1 word2 ..."
      *NP${MAX_INTERVAL},${ADDITIONAL_LAST_INTERVAL},${MAX_PHRASE_INTERVAL_1}|${MAX_PHRASE_INTERVAL_2}|...,${MIN_INTERVAL} "phrase1 phrase2 ..."
      *NPP${MAX_INTERVAL},${ADDITIONAL_LAST_INTERVAL},${MAX_PHRASE_INTERVAL_1}|${MAX_PHRASE_INTERVAL_2}|...,${MIN_INTERVAL} "(phrase1-1 phrase1-2 ...) (phrase2-1 phrase2-2 ...) ..."
      *ONP${MAX_INTERVAL},${ADDITIONAL_LAST_INTERVAL},${MAX_PHRASE_INTERVAL_1}|${MAX_PHRASE_INTERVAL_2}|...,${MIN_INTERVAL} "phrase1 phrase2 ..."
      *ONPP${MAX_INTERVAL},${ADDITIONAL_LAST_INTERVAL},${MAX_PHRASE_INTERVAL_1}|${MAX_PHRASE_INTERVAL_2}|...,${MIN_INTERVAL} "(phrase1-1 phrase1-2 ...) (phrase2-1 phrase2-2 ...) ..."

  `${MIN_INTERVAL}` のデフォルト値は `INT32_MIN` (`-2147483648`) です。`${MIN_INTERVAL}` を省略した場合デフォルト値が使用されます。

  このオプションは重複したフレーズを無視するのに便利です。

  `*NP` の距離は `各フレーズの先頭のトークンの距離 - 左のフレーズのトークン数 + 1` で計算されます。

  トークナイザーがバイグラムの場合を考えると、例えば、 `東京` は `東京` という一つのトークンを持ち、 `京都` は `京都` という一つのトークンを持ちます。

  `*NP "東京 京都"` の対象の値として `東京都` を考えてみます。

  - `各フレーズの先頭のトークンの距離`: `1` (`東京` と `京都` の距離)

  - `左のフレーズのトークン数`: `1` ( `東京` )

  `東京都` に対して `*NP` で使われる距離は、 `1 - 1 + 1` = `1` となります。

  結果として、 `東京` と `京都` が重複していないとき、 `*NP` で使われる距離は `1` より大きくなります。

  このオプションは重複したフレーズを無視するのに便利です。

      table_create Entries TABLE_NO_KEY
      column_create Entries content COLUMN_SCALAR Text

      table_create Terms TABLE_PAT_KEY ShortText \
        --default_tokenizer 'TokenNgram("unify_alphabet", false, \
                                        "unify_digit", false)' \
        --normalizer NormalizerNFKC150
      column_create Terms entries_content COLUMN_INDEX|WITH_POSITION Entries content

      load --table Entries
      [
      {"content": "東京都"},
      {"content": "東京京都"}
      ]

      select Entries \
        --match_columns content \
        --query '*NP-1,0,,2"東京 京都"' \
        --output_columns '_score, content'
      #[
      #  [
      #    0,
      #    0.0,
      #    0.0
      #  ],
      #  [
      #    [
      #      [
      #        1
      #      ],
      #      [
      #        [
      #          "_score",
      #          "Int32"
      #        ],
      #        [
      #          "content",
      #          "Text"
      #        ]
      #      ],
      #      [
      #        1,
      #        "東京京都"
      #      ]
      #    ]
      #  ]
      #]

  上記の例では、 `東京都` は距離が `1` なのでマッチしませんが、 `東京京都` は距離が `2` なのでマッチします。

- [ノーマライザー] `unify_katakana_trailing_o` オプションで新しい値をサポートしました。

  `unify_katakana_trailing_o` で以下の新しい値のノーマライズをサポートしました。これらの左側の文字の母音が `オ` なので、ノーマライズすべきなためです。

  - `ォオ` -> `ォウ`

  - `ョオ` -> `ョウ`

  - `ヺオ` -> `ヺウ`

- MessagePack v6.0.0 をサポートしました。 [GitHub#1536][Reported by Carlo Cabrera]

  今まで、Groongaは `configure` または `cmake` 実行時にMessagePack v6.0.0以降のMessagePackを検出できませんでした。このリリースから、MessagePackがv6.0.0以降であっても検出できるようになります。

### 修正

- [ノーマライザー] NormalizerNFKCが不正な正規化をする問題を修正しました。

  この問題は、 `unify_kana_case` と `unify_katakana_v_sounds` を同時に使う場合に発生します。

  例えば、 `unify_kana_case` と `unify_katakana_v_sounds` を同時に使うとき、 `ヴァ` が `バア` にノーマライズされていました。しかし `ヴァ` は `バ` と正規化されるべきです。

  これは、 `unify_kana_case` で `ヴァ` が `ヴア` と正規化され、その後、 `unify_katakana_v_sounds` によって `ヴア` が `バア` と正規化されていたことが原因です。`unify_katakana_v_sounds` が `unify_kana_case` より前に適用されるように修正しました。

  以下は以前のバージョンでの問題の発生例です。

      normalize \
      'NormalizerNFKC150("unify_katakana_v_sounds", true, \
                        "unify_kana_case", true)' \
      "ヴァーチャル"
      #[
      #  [
      #    0,
      #    1678097412.913053,
      #    0.00019073486328125
      #  ],
      #  {
      #    "normalized":"ブアーチヤル",
      #    "types":[],
      #    "checks":[]
      #  }

  このバージョンから、 `ヴァーチャル` は `バーチヤル` にノーマライズされます。

- [順序付き近傍フレーズ検索条件][順序付き近傍フレーズ検索演算子] `${MAX_PHRASE_INTERVALS}` が正しく動かない問題を修正しました。

  この問題が発生したとき、距離は `0` とみなされます。したがって、この問題が発生した場合、余分にレコードがヒットすることがあります。

  この問題は以下の場合に発生します。

  1. `*ONP` で `${MAX_PHRASE_INTERVALS}` を使用している

  2. マッチした左側のフレーズに含まれるトークンの数が、 `${MAX_PHRASE_INTERVALS}` で指定した要素数より多い

  以下はこの問題の例です。

      table_create Entries TABLE_NO_KEY
      column_create Entries content COLUMN_SCALAR Text
      table_create Terms TABLE_PAT_KEY ShortText \
        --default_tokenizer 'TokenNgram("unify_alphabet", false, \
                                        "unify_digit", false)' \
        --normalizer NormalizerNFKC150
      column_create Terms entries_content COLUMN_INDEX|WITH_POSITION Entries content
      load --table Entries
      [
      {"content": "abcXYZdef"},
      {"content": "abcdef"},
      {"content": "abc123456789def"},
      {"content": "abc12345678def"},
      {"content": "abc1de2def"}
      ]
      select Entries --filter 'content *ONP-1,0,1 "abc def"' --output_columns '_score, content'
      #[
      #  [
      #    0,
      #    0.0,
      #    0.0
      #  ],
      #  [
      #    [
      #      [
      #        5
      #      ],
      #      [
      #        [
      #          "_score",
      #          "Int32"
      #        ],
      #        [
      #          "content",
      #          "Text"
      #        ]
      #      ],
      #      [
      #        1,
      #        "abcXYZdef"
      #      ],
      #      [
      #        1,
      #        "abcdef"
      #      ],
      #      [
      #        1,
      #        "abc123456789def"
      #      ],
      #      [
      #        1,
      #        "abc12345678def"
      #      ],
      #      [
      #        1,
      #        "abc1de2def"
      #      ]
      #    ]
      #  ]
      #]

  上記の例では、 `*ONP-1,0,1 "abc def"` で、最初の要素の距離に `1` を指定しています。しかし、距離が `1` より離れているものも含めた、すべての `content` がマッチしています。

  これは、この例がこの問題の発生条件を満たしていて、距離が `0` とみなされているためです。

  1. `*ONP` で `${MAX_PHRASE_INTERVALS}` を使用している

     `*ONP-1,0,1 "abc def"` は `${MAX_PHRASE_INTERVALS}` を使用している。

  2. マッチした左側のフレーズに含まれるトークンの数が、 `${MAX_PHRASE_INTERVALS}` で指定した要素数より多い

     - マッチした左側のフレーズ: `abc`

       - 含まれるトークン: `ab` 、 `bc`

       - `TokenNgram("unify_alphabet", false, "unify_digit", false)` によるトークナイズ

     - 左側のフレーズに含まれるトークン数 (`2`) > `max_element_intervals` にに含まれる要素数 (`1`)

       - `*ONP-1,0,1 "abc def"` の `1`

     - 左側のフレーズに含まれるトークン数 (`2`) > `max_element_intervals` にに含まれる要素数 (`1`)

- [近傍フレーズ検索条件][近傍フレーズ検索演算子] 各近傍フレーズ検索で、最後として指定したフレーズが最後として使用されない問題を修正しました。

  この問題が発生すると `${ADDITIONAL_LAST_INTERVAL}` は無視され、 `${MAX_INTERVAL}` が使用されます。

  この問題は以下の場合に発生します。

  1. 最後として指定されたフレーズが複数のトークンを含む

  2. そのフレーズの最後のトークンのサイズが、他のトークンのサイズ以下である

     - トークンサイズとは、全レコード中に出現するそのトークンの数です。

  以下はこの問題の例です。

      table_create Entries TABLE_NO_KEY
      column_create Entries content COLUMN_SCALAR Text

      table_create Terms TABLE_PAT_KEY ShortText \
        --default_tokenizer 'TokenNgram("unify_alphabet", false, \
                                        "unify_digit", false)' \
        --normalizer NormalizerNFKC150
      column_create Terms entries_content COLUMN_INDEX|WITH_POSITION Entries content

      load --table Entries
      [
      {"content": "abc123456789defg"},
      {"content": "dededede"}
      ]

      select Entries \
        --filter 'content *NP10,1"abc defg$"' \
        --output_columns '_score, content'
      #[
      #  [
      #    0,
      #    0.0,
      #    0.0
      #  ],
      #  [
      #    [
      #      [
      #        0
      #      ],
      #      [
      #        [
      #          "_score",
      #          "Int32"
      #        ],
      #        [
      #          "content",
      #          "Text"
      #        ]
      #      ]
      #    ]
      #  ]
      #]

  上記の例の `abc123456789defg` について考えると、 `abc` から `defg` までの距離は `11` です。 `${MAX_INTERVAL}` は `10` で `${ADDITIONAL_LAST_INTERVAL}` は `1` が指定されています。したがって、最後のフレーズがマッチするしきい値は11になります。以上から、 `abc123456789defg` はマッチするはずですが、していません。

  これは、この例が、以下のようにこの問題の発生条件を満たしていて、`${MAX_INTERVAL}` のみが使われているためです。

  1. 最後として指定されたフレーズが複数のトークンを含む

     最後に `$` がついているので、 `defg$` は最後と指定されています。

     `defg$` は `TokenNgram("unify_alphabet", false, "unify_digit", false)` によって `de`, `ef`, `fg` にトークナイズされます。

  2. そのフレーズの最後のトークンのサイズが、他のトークンのサイズ以下である

     `fg` は `defg$` の最後のトークンです。 `abc123456789defg` は1つの `fg` と `de` を含みます。そして、 `dededede` は4つの `de` を含みます。

     したがって、 `fg` のサイズは `1` で、 `de` のサイズは `5` です。

- [近傍フレーズ検索条件] 距離の計算方法を修正しました。

  この問題によって、近傍フレーズ検索を使った場合に、ヒットしないはずのレコードがヒットすることがあります。

- [highlight_html] `loose_symbol=true` の時にハイライト位置がずれることがある問題を修正しました。

### 感謝

- Carlo Cabreraさん

## 13.0.0リリース - 2023-02-09

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

まずはじめに 13.0.0の主な変更点を紹介します。次に、Groonga 12.0.0 から 12.1.2 までの変更点を紹介します。

### 13.0.0の新規機能と改良

### 改良

- [ノーマライザー] Unicode 15.0 の NFKC（Normalization Form Compatibility Composition）をベースにしたノーマライザー `NormalizerNFKC150` を新しく追加しました。

- [トークンフィルター] Unicode 15.0 の NFKC（Normalization Form Compatibility Composition）をベースにしたトークンフィルター `TokenFilterNFKC150` を新しく追加しました。

- [NormalizerNFKC150] `NormalizerNFKC` に以下の新しいオプションを追加しました。

  - `unify_katakana_gu_small_sounds`

    このオプションを使うことで、"グァ -> ガ", "グィ -> ギ", "グェ -> ゲ", "グォ -> ゴ"と正規化できます。

    以下は `unify_katakana_gu_small_sounds` オプションの使用例です。

        table_create --name Countries --flags TABLE_HASH_KEY --key_type ShortText
        column_create --table Countries --name name --type ShortText
        load --table Countries
        [
        {"_key":"JP","name":"日本"},
        {"_key":"GT","name":"グァテマラ共和国"},
        ]

        table_create \
          --name idx_contry_name \
          --flags TABLE_PAT_KEY \
          --key_type ShortText \
          --default_tokenizer TokenBigram \
          --normalizer 'NormalizerNFKC150("unify_katakana_gu_small_sounds", true)'
        column_create --table idx_contry_name --name contry_name --flags COLUMN_INDEX|WITH_POSITION --type Countries --source name

        select --table Countries --query name:@ガテマラ共和国
        [
          [0,
           0,
           0
          ],
          [
            [
              [
                1
              ],
              [
                [
                  "_id",
                  "UInt32"
                ],
                [
                  "_key",
                  "ShortText"
                ],
                [
                  "name",
                  "ShortText"
                ]
              ],
              [
                2,
                "GT",
                "グァテマラ共和国"
              ]
            ]
          ]
        ]

  - `unify_katakana_di_sound`

    このオプションを使うことで、"ヂ -> ジ"と正規化できます。

    以下は、 `unify_katakana_di_sound` オプションの使用例です。

        table_create --name Foods --flags TABLE_HASH_KEY --key_type ShortText
        column_create --table Foods --name name --type ShortText
        load --table Foods
        [
        {"_key":"1","name":"チジミ"},
        {"_key":"2","name":"パジョン"},
        ]

        table_create \
          --name idx_food_name \
          --flags TABLE_PAT_KEY \
          --key_type ShortText \
          --default_tokenizer TokenBigram \
          --normalizer 'NormalizerNFKC150("unify_katakana_di_sound", true)'
        column_create --table idx_food_name --name food_name --flags COLUMN_INDEX|WITH_POSITION --type Foods --source name

        select --table Foods --query name:@チヂミ
        [
          [
            0,
            0,
            0
          ],
          [
            [
              [
                1
              ],
              [
                [
                  "_id",
                  "UInt32"
                ],
                [
                  "_key",
                  "ShortText"
                ],
                [
                  "name",
                  "ShortText"
                ]
              ],
              [
                1,
                "1",
                "チジミ"
              ]
            ]
          ]
        ]

  - `unify_katakana_wo_sound`

    このオプションを使うことで、"ヲ -> オ"と正規化できます。

    以下は、 `unify_katakana_wo_sound` オプションの使用例です。

        table_create --name Foods --flags TABLE_HASH_KEY --key_type ShortText
        column_create --table Foods --name name --type ShortText
        load --table Foods
        [
        {"_key":"1","name":"アヲハタ"},
        {"_key":"2","name":"ヴェルデ"},
        {"_key":"3","name":"ランプ"},
        ]

        table_create \
          --name idx_food_name \
          --flags TABLE_PAT_KEY \
          --key_type ShortText \
          --default_tokenizer TokenBigram \
          --normalizer 'NormalizerNFKC150("unify_katakana_wo_sound", true)'
        column_create --table idx_food_name --name food_name --flags COLUMN_INDEX|WITH_POSITION --type Foods --source name

        select --table Foods --query name:@アオハタ
        [
          [
            0,
            0,
            0
          ],
          [
            [
              [
                1
              ],
              [
                [
                  "_id",
                  "UInt32"
                ],
                [
                  "_key",
                  "ShortText"
                ],
                [
                  "name",
                  "ShortText"
                ]
              ],
              [
                1,
                "1",
                "アヲハタ"
              ]
            ]
          ]
        ]

  - `unify_katakana_zu_small_sounds`

    このオプションを使うことで、"ズァ -> ザ", "ズィ -> ジ", "ズェ -> ゼ", "ズォ -> ゾ"と正規化できます。

    以下は、 `unify_katakana_zu_small_sounds` オプションの使用例です。

        table_create --name Cities --flags TABLE_HASH_KEY --key_type ShortText
        column_create --table Cities --name name --type ShortText
        load --table Cities
        [
        {"_key":"1","name":"ガージヤーバード"},
        {"_key":"2","name":"デリー"},
        ]

        table_create \
          --name idx_city_name \
          --flags TABLE_PAT_KEY \
          --key_type ShortText \
          --default_tokenizer TokenBigram \
          --normalizer 'NormalizerNFKC150("unify_katakana_zu_small_sounds", true)'
        column_create --table idx_city_name --name city_name --flags COLUMN_INDEX|WITH_POSITION --type Cities --source name

        select --table Cities --query name:@ガーズィヤーバード
        [
          [
            0,
            0,
            0
          ],
          [
            [
              [
                1
              ],
              [
                [
                  "_id",
                  "UInt32"
                ],
                [
                  "_key",
                  "ShortText"
                ],
                [
                  "name",
                  "ShortText"
                ]
              ],
              [
                1,
                "1",
                "ガージヤーバード"
              ]
            ]
          ]
        ]

  - `unify_katakana_du_sound`

    このオプションを使うことで、"ヅ -> ズ"と正規化できます。

    以下は、 `unify_katakana_du_sound` オプションの使用例です。

        table_create --name Plants --flags TABLE_HASH_KEY --key_type ShortText
        column_create --table Plants --name name --type ShortText
        load --table Plants
        [
        {"_key":"1","name":"ハスノカヅラ"},
        {"_key":"2","name":"オオツヅラフジ"},
        {"_key":"3","name":"アオツヅラフジ"},
        ]

        table_create \
          --name idx_plant_name \
          --flags TABLE_PAT_KEY \
          --key_type ShortText \
          --default_tokenizer TokenBigram \
          --normalizer 'NormalizerNFKC150("unify_katakana_du_sound", true)'
        column_create --table idx_plant_name --name plant_name --flags COLUMN_INDEX|WITH_POSITION --type Plants --source name

        select --table Plants --query name:@ツズラ
        [
          [
            0,
            0,
            0
          ],
          [
            [
              [
                2
              ],
              [
                [
                  "_id",
                  "UInt32"
                ],
                [
                  "_key",
                  "ShortText"
                ],
                [
                  "name",
                  "ShortText"
                ]
              ],
              [
                2,
                "2",
                "オオツヅラフジ"
              ],
              [
                3,
                "3",
                "アオツヅラフジ"
              ]
            ]
          ]
        ]

  - `unify_katakana_trailing_o`

    このオプションによって、以下の文字を正規化できます。

    > - "オオ -> オウ"

    > - "コオ -> コウ"

    > - "ソオ -> ソウ"

    > - "トオ -> トウ"

    > - "ノオ -> ノウ"

    > - "ホオ -> ホウ"

    > - "モオ -> モウ"

    > - "ヨオ -> ヨウ"

    > - "ロオ -> ロウ"

    > - "ゴオ -> ゴウ"

    > - "ゾオ -> ゾウ"

    > - "ドオ -> ドウ"

    > - "ボオ -> ボウ"

    > - "ポオ -> ポウ"

    以下は、 `unify_katakana_trailing_o` オプションの使用例です。

        table_create --name Sharks --flags TABLE_HASH_KEY --key_type ShortText
        column_create --table Sharks --name name --type ShortText
        load --table Sharks
        [
        {"_key":"1","name":"ホオジロザメ"},
        {"_key":"2","name":"ジンベイザメ"},
        ]

        table_create \
          --name idx_shark_name \
          --flags TABLE_PAT_KEY \
          --key_type ShortText \
          --default_tokenizer TokenBigram \
          --normalizer 'NormalizerNFKC150("unify_katakana_trailing_o", true)'
        column_create --table idx_shark_name --name shark_name --flags COLUMN_INDEX|WITH_POSITION --type Sharks --source name

        select --table Sharks --query name:@ホウジロザメ
        [
          [
            0,
            0,
            0
          ],
          [
            [
              [
                1
              ],
              [
                [
                  "_id",
                  "UInt32"
                ],
                [
                  "_key",
                  "ShortText"
                ],
                [
                  "name",
                  "ShortText"
                ]
              ],
              [
                1,
                "1",
                "ホオジロザメ"
              ]
            ]
          ]
        ]

  - `unify_katakana_du_small_sounds`

    このオプションを使うことで、 "ヅァ -> ザ", "ヅィ -> ジ", "ヅェ -> ゼ", "ヅォ -> ゾ"と正規化できます。

    以下は、 `unify_katakana_du_small_sounds` オプションの使用例です。

        table_create --name Airports --flags TABLE_HASH_KEY --key_type ShortText
        column_create --table Airports --name name --type ShortText
        load --table Airports
        [
        {"_key":"HER","name":"イラクリオ・ニコスカザンヅァキス国際空港"},
        {"_key":"ATH","name":"アテネ国際空港"},
        ]

        table_create \
          --name idx_airport_name \
          --flags TABLE_PAT_KEY \
          --key_type ShortText \
          --default_tokenizer TokenBigram \
          --normalizer 'NormalizerNFKC150("unify_katakana_du_small_sounds", true)'
        column_create --table idx_airport_name --name airport_name --flags COLUMN_INDEX|WITH_POSITION --type Airports --source name

        select --table Airports --query name:@ニコスカザンザキス
        [
          [
            [
              1
            ],
            [
              [
                "_id",
                "UInt32"
              ],
              [
                "_key",
                "ShortText"
              ],
              [
                "name",
                "ShortText"
              ]
            ],
            [
              1,
              "HER",
              "イラクリオ・ニコスカザンヅァキス国際空港"
            ]
          ]
        ]

- [Oracle Linux] Oracle Linux 8と9 向けのパッケージを新しくサポートしました。

### Groonga 12.0.0 から 12.1.2 までの主な変更点

### ハイライト

[12.0.9リリース - 2022-10-28]

> - [ノーマライザー] `NormalizerHTML` を追加しました。（実験的）

>   `NormalizerHTML` はHTML用のノーマライザーです。

>   現在 `NormalizerHTML` は `<span>` や `</span>` といったタグの削除と、`&amp;` や `&#38;` といった文字参照の展開を行います。

>   以下は `NormalizerHTML` の例です。

>       normalize NormalizerHTML "<span> Groonga &amp; Mroonga &#38; Rroonga </span>"
>       [[0,1666923364.883798,0.0005481243133544922],{"normalized":" Groonga & Mroonga & Rroonga ","types":[],"checks":[]}]

>   この例では、 `<span>` と `</span>` は削除され、 `&amp;` と `&#38;` は `&` に展開されています。

>   タグを削除するかどうかは `remove_tag` オプションで指定できます。(`remove_tag` オプションのデフォルト値は `true` です。)

>       normalize 'NormalizerHTML("remove_tag", false)' "<span> Groonga &amp; Mroonga &#38; Rroonga </span>"
>       [[0,1666924069.278549,0.0001978874206542969],{"normalized":"<span> Groonga & Mroonga & Rroonga </span>","types":[],"checks":[]}]

>   この例では、 `<span>` と `</span>` は削除されていません。

>   文字参照を展開するかどうかは `expand_character_reference` オプションで指定できます。(`expand_character_reference` オプションのデフォルト値は `true` です。)

>       normalize 'NormalizerHTML("expand_character_reference", false)' "<span> Groonga &amp; Mroonga &#38; Rroonga </span>"
>       [[0,1666924357.099782,0.0002346038818359375],{"normalized":" Groonga &amp; Mroonga &#38; Rroonga ","types":[],"checks":[]}]

>   この例では、 `&amp;` と `&#38;` は展開されていません。

[12.0.3リリース - 2022-04-29]

> - [snippet],[snippet_html] 入力としてベクターをサポートしました。[groonga-dev,04956][Reported by shinonon]

>   例えば、以下のようにJSONデータ内のベクターに対して検索キーワードの周辺テキストを抽出できます。

>       table_create Entries TABLE_NO_KEY
>       column_create Entries title COLUMN_SCALAR ShortText
>       column_create Entries contents COLUMN_VECTOR ShortText

>       table_create Tokens TABLE_PAT_KEY ShortText   --default_tokenizer TokenNgram   --normalizer NormalizerNFKC130
>       column_create Tokens entries_title COLUMN_INDEX|WITH_POSITION Entries title
>       column_create Tokens entries_contents COLUMN_INDEX|WITH_SECTION|WITH_POSITION   Entries contents

>       load --table Entries
>       [
>       {
>         "title": "Groonga and MySQL",
>         "contents": [
>           "Groonga is a full text search engine",
>           "MySQL is a RDBMS",
>           "Mroonga is a MySQL storage engine based on Groonga"
>         ]
>       }
>       ]

>       select Entries\
>         --output_columns 'snippet_html(contents), contents'\
>         --match_columns 'title'\
>         --query Groonga
>       [
>         [
>           0,
>           0.0,
>           0.0
>         ],
>         [
>           [
>             [
>               1
>             ],
>             [
>               [
>                 "snippet_html",
>                 null
>               ],
>               [
>                 "contents",
>                 "ShortText"
>               ]
>             ],
>             [
>               [
>                 "<span class=\"keyword\">Groonga</span> is a full text search engine",
>                 "Mroonga is a MySQL storage engine based on <span class=\"keyword\">Groonga</span>"
>               ],
>               [
>                 "Groonga is a full text search engine",
>                 "MySQL is a RDBMS",
>                 "Mroonga is a MySQL storage engine based on Groonga"
>               ]
>             ]
>           ]
>         ]
>       ]

>   今までも、 `--output_columns 'snippet_html(contents[1])'` のように `snippet*` を指定することで以下のようにベクターに対して検索キーワードの周辺テキストを抽出できますが、この方法ではどの要素を出力すればよいかわかりません。どの要素が検索にヒットしたかわからないためです。

>       select Entries\
>         --output_columns 'snippet_html(contents[0]), contents'\
>         --match_columns 'title'\
>         --query Groonga
>       [
>         [
>           0,
>           0.0,
>           0.0
>         ],
>         [
>           [
>             [
>               1
>             ],
>             [
>               [
>                 "snippet_html",
>                 null
>               ],
>               [
>                 "contents",
>                 "ShortText"
>               ]
>             ],
>             [
>               [
>                 "<span class=\"keyword\">Groonga</span> is a full text search engine"
>               ],
>               [
>                 "Groonga is a full text search engine",
>                 "MySQL is a RDBMS",
>                 "Mroonga is a MySQL storage engine based on Groonga"
>               ]
>             ]
>           ]
>         ]
>       ]

[12.0.1リリース - 2022-02-28]

> - [query_expand] 同義語グループをサポートしました。

>   同義語検索をする場合、今までは、以下のようにキーワードとその同義語をそれぞれ定義していました。

>       table_create Thesaurus TABLE_PAT_KEY ShortText --normalizer NormalizerAuto
>       # [[0, 1337566253.89858, 0.000355720520019531], true]
>       column_create Thesaurus synonym COLUMN_VECTOR ShortText
>       # [[0, 1337566253.89858, 0.000355720520019531], true]
>       load --table Thesaurus
>       [
>       {"_key": "mroonga", "synonym": ["mroonga", "tritonn", "groonga mysql"]},
>       {"_key": "groonga", "synonym": ["groonga", "senna"]}
>       ]

>   上記のケースでは、`mroonga` を検索した場合、 Groongaは、意図通り、 `mroonga OR tritonn OR "groonga mysql" を検索しますが、``tritonn` を検索した場合は、 Groongaは、 `tritonn` のみを検索します。`tritonn` を検索した場合でも、`tritonn OR mroonga OR "groonga mysql"` と検索した場合、以下のように定義を追加する必要がありました。

>       load --table Thesaurus
>       [
>       {"_key": "tritonn", "synonym": ["tritonn", "mroonga", "groonga mysql"]},
>       ]

>   多くのケースでは、 `mroonga` を `mroonga OR tritonn OR "groonga mysql"` と展開した場合、 `tritonn` や `"groonga mysql"` も `mroonga OR tritonn OR "groonga mysql"` と展開して欲しくなりますが、今までは、そのようなケースでは定義を追加する必要がありました。したがって、対象のキーワードに同義語がたくさんあると、同じような定義をたくさん定義する必要があるため、同義語の定義が煩雑でした。

>   加えて、同義語を削除する際も、多くのレコードを削除する必要があるので面倒でした。

>   今回のリリースから同義語の代表値を決めることで一つのグループを作れるようになりました。例えば、以下のすべてのキーワードは、 "mroonga" グループです。

>       load --table Synonyms
>       [
>         {"_key": "mroonga": "representative": "mroonga"}
>       ]

>       load --table Synonyms
>       [
>         {"_key": "tritonn": "representative": "mroonga"},
>         {"_key": "groonga mysql": "representative": "mroonga"}
>       ]

>   このケースでは、 `mroonga` は `mroonga OR tritonn OR "groonga mysql"` と展開されます。また、 `tritonn` や `"groonga mysql"` も `mroonga OR tritonn OR "groonga mysql"` と展開されます。

>   同義語を削除する際も、対象のレコードを削除するだけです。例えば、同義語から `"groonga mysql"` を削除する場合は、 `{"_key": "groonga mysql": "representative": "mroonga"}` を削除するだけです。

[12.0.0リリース - 2022-02-09]

> - [index_column_have_source_record] 新しい関数 `index_column_have_source_record()` を追加しました。

>   インデックスに存在するトークンがGroongaに登録されているいずれかのレコードに含まれているかどうかを確認できます。

>   Groongaは、レコードの更新によってどのレコードからも使われていないトークンがあっても、それを削除しません。したがって、例えば、オートコンプリート機能を使っていると、検索候補としてどのレコードにも含まれていないトークンを返す可能性がありますが、この関数をつかうことで、不要なトークンを返さないようにできます。

>   この関数は、トークンがどのレコードにも含まれていないことを検出できるからです。

> - [select] 新しい引数 `drilldown_max_n_target_records` と `drilldown[${LABEL}].max_n_target_records` を追加しました。

>   ドリルダウン対象のテーブル（フィルター結果）の中のうち最大で何レコードをドリルダウンに使うかを指定します。もし、フィルター結果のレコード数が指定した値より大きかったらフィルターした結果内のいくつかのレコードはドリルダウンには使われません。これらの引数のデフォルト値は、 `-1` です。これらの引数に `-1` がセットされた場合、Groongaは全てのレコードをドリルダウンに使います。

>   この機能はフィルター結果が非常に大きくなるかもしれない場合に有用です。大きなフィルター結果に対するドリルダウンは遅くなることがあるためです。この機能を使うことでドリルダウンに使うレコード数を制限できます。

>   以下はドリルダウンに使う最大レコード数を制限する例です。最後の2レコード（ `{"_id": 4, "tag": "Senna"}` と `{"_id": 5, "tag": "Senna"}` ）は使われていません。

>       table_create Entries TABLE_HASH_KEY ShortText
>       column_create Entries content COLUMN_SCALAR Text
>       column_create Entries n_likes COLUMN_SCALAR UInt32
>       column_create Entries tag COLUMN_SCALAR ShortText

>       table_create Terms TABLE_PAT_KEY ShortText --default_tokenizer TokenBigram --normalizer NormalizerAuto
>       column_create Terms entries_key_index COLUMN_INDEX|WITH_POSITION Entries _key
>       column_create Terms entries_content_index COLUMN_INDEX|WITH_POSITION Entries content
>       load --table Entries
>       [
>       {"_key":    "The first post!",
>        "content": "Welcome! This is my first post!",
>        "n_likes": 5,
>        "tag": "Hello"},
>       {"_key":    "Groonga",
>        "content": "I started to use Groonga. It's very fast!",
>        "n_likes": 10,
>        "tag": "Groonga"},
>       {"_key":    "Mroonga",
>        "content": "I also started to use Mroonga. It's also very fast! Really fast!",
>        "n_likes": 15,
>        "tag": "Groonga"},
>       {"_key":    "Good-bye Senna",
>        "content": "I migrated all Senna system!",
>        "n_likes": 3,
>        "tag": "Senna"},
>       {"_key":    "Good-bye Tritonn",
>        "content": "I also migrated all Tritonn system!",
>        "n_likes": 3,
>        "tag": "Senna"}
>       ]

>       select Entries \
>         --limit -1 \
>         --output_columns _id,tag \
>         --drilldown tag \
>         --drilldown_max_n_target_records 3
>       [
>         [
>           0,
>           1337566253.89858,
>           0.000355720520019531
>         ],
>         [
>           [
>             [
>               5
>             ],
>             [
>               [
>                 "_id",
>                 "UInt32"
>               ],
>               [
>                 "tag",
>                 "ShortText"
>               ]
>             ],
>             [
>               1,
>               "Hello"
>             ],
>             [
>               2,
>               "Groonga"
>             ],
>             [
>               3,
>               "Groonga"
>             ],
>             [
>               4,
>               "Senna"
>             ],
>             [
>               5,
>               "Senna"
>             ]
>           ],
>           [
>             [
>               2
>             ],
>             [
>               [
>                 "_key",
>                 "ShortText"
>               ],
>               [
>                 "_nsubrecs",
>                 "Int32"
>               ]
>             ],
>             [
>               "Hello",
>               1
>             ],
>             [
>               "Groonga",
>               2
>             ]
>           ]
>         ]
>       ]

### 概要

### 改良

[12.1.2リリース - 2023-01-29]

> - [httpd] バンドルしているnginxのバージョンを1.23.3に更新しました。

[12.1.1リリース - 2023-01-06]

> - [select][POWER_SET] ドリルダウンでベクターのべき集合を集計できるようになりました。

> - [select] ベクターカラムの特定の要素のみを対象に検索できるようになりました。

> - [load] `YYYY-MM-DD` 形式をサポートしました。

[12.1.0 リリース - 2022-11-29]

> - [load] `load` のスローログの出力に対応しました。

> - [API] 新しいAPI `grn_is_reference_count_enable()` を追加しました。

> - [status] 新しい項目 `back_trace` と `reference_count` を追加しました。

[12.0.9リリース - 2022-10-28]

> - [AlmaLinux] AlmaLinux 9 向けのパッケージをサポートしました。

> - [escalate] `escalate()` 関数のドキュメントを追加しました。

> - [ノーマライザー] `NormalizerHTML` を追加しました。（実験的）

> - [httpd] バンドルしているnginxのバージョンを1.23.2に更新しました。

> - メモリーが不足した際に、同じログが大量に出力されないように変更しました。

[12.0.8リリース - 2022-10-03]

> - `escalate()` 関数（実験的）の仕様を使いやすいように変更しました。

> - [CMakeを使ってGroongaをビルドする方法] CMakeを使ってビルドする方法を追加しました。

> - [その他] GNU Autotoolsを使ってビルドする場合に、Apache Arrowの機能を有効化/無効化する方法について追加しました。

> - [select] drilldowns[${LABEL}].table のドキュメントを追加しました。

> - [国際化] 翻訳方法を更新しました。

[12.0.7リリース - 2022-08-29]

> - 新しい関数 `escalate()` を追加しました。(実験的)

> - [httpd] バンドルしているnginxのバージョンを1.23.1に更新しました。

> - [select] `--n_workers` オプションのドキュメントを追加しました。

[12.0.6リリース - 2022-08-04]

> - groonga-delta用の新しいMuninプラグインを追加しました。

> - [column_copy] 重み付きベクターをサポートしました。

> - [Ubuntu] Ubuntu 21.10 (Impish Indri) のサポートをやめました。

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

[12.0.5リリース - 2022-06-29]

> - [select] 検索エスカレーションによる前方一致検索のパフォーマンスを少し改善しました。

> - [select] `drilldowns[LABEL]._key` に重み付き参照ベクターカラムを指定できるようになりました。

> - [select] `query` や `filter` や `post_filter` を使っていても、ドリルダウンのキーに重み付き参照ベクターカラムを指定できるようになりました。

[12.0.4リリース - 2022-06-06]

> - [Ubuntu] Ubuntu 22.04 (Jammy Jellyfish)をサポートしました。

> - groonga-benchmark の提供をやめました。

> - [status] 新しい項目 `memory_map_size` を追加しました。

[12.0.3リリース - 2022-04-29]

> - [logical_count] `logical_count` 実行中のメモリー使用量を改善しました。

> - [dump] `MISSING_IGNORE/MISSING_NIL` をサポートしました。

> - [snippet],[snippet_html] 入力としてベクターをサポートしました。

> - [`vector_join`] 新しい関数 `vector_join()` を追加しました。

> - [インデックス構築] 動的インデックス構築のようにとても大きなトークンを無視するようにしました。

[12.0.2リリース - 2022-03-29]

> - [logical_range_filter] シャードを処理した直後に参照を減らすようにしました。

> - クラッシュリカバリー機能の安定性が向上しました。

> - 無名マッピングが利用可能な時のmmapのパフォーマンスを向上しました。

> - [インデックス構築] 以下のタイプのカラムで静的インデックス構築をサポートしました。

> - [column_create] 新しいフラグ `MISSING_*` と `INVALID_*` を追加しました。

> - [dump][column_list] `MISSING_*` と `INVALID_*` フラグをサポートしました。

> - [schema] `MISSING_*` と `INVALID_*` フラグをサポートしました。

> - Amazon Linux 2向けのパッケージを提供するようにしました。

> - [Windows] Visual Studio 2017 でのビルドをやめました。

[12.0.1リリース - 2022-02-28]

> - [query_expand] 同義語グループをサポートしました。

> - [query_expand] 同義語グループにベクターを使えるようにしました。

> - 環境変数によって、バックトレースを無効にできるようにしました。

> - [select] `--slices` のパフォーマンスを改善しました。

> - [Windows] VisualStudio 2022 をサポートしました。

> - [select] 近傍検索でそれぞれの要素ごとの距離を指定できるようになりました。

> - [Groonga HTTPサーバー] RPMパッケージのGroongaであっても、 `groonga-server-http` を使えるようにしました。

[12.0.0リリース - 2022-02-09]

> - [sub_filter] 新しいオプション `pre_filter_threshold` を追加しました。

> - [index_column_have_source_record] 新しい関数 `index_column_have_source_record()` を追加しました。

> - [NormalizerNFKC130] 新しいオプション `strip` を追加しました。

> - [select] 新しい引数 `drilldown_max_n_target_records` と `drilldown[${LABEL}].max_n_target_records` を追加しました。

> - [httpd] バンドルしているnginxのバージョンを1.21.6に更新しました。

### 修正

[12.1.1リリース - 2023-01-06]

> - [select] `command_version` が `3` のとき、 `drilldown` の結果のラベルが不正になる問題を修正しました。

> - [NormalizerTable] 特定の定義が `NormalizerTable` に存在する場合、Groongaがクラッシュすることがある問題を修正しました。

[12.1.0 リリース - 2022-11-29]

> - [select][ベクターカラム] 重み付きベクターカラムで `WEIGHT_FLOAT32` を指定したとき、結果が整数で表示されていた問題を修正しました。

[12.0.9リリース - 2022-10-28]

> - [select] n_workers を指定したとき、Groongaがクラッシュしたり、誤った結果を返すことがある問題を修正しました。

[12.0.8リリース - 2022-10-03]

> - NormalizerTable で冪等でない（繰り返し実行すると結果が変わることがある）定義をした時に、Groongaが誤った結果を返すことがある問題を修正しました。

[12.0.7リリース - 2022-08-29]

> - OR検索実行中に `request_cancel` を実行した場合、Groongaの応答が遅くなることがある問題を修正しました。

[12.0.6リリース - 2022-08-04]

> - `n_workers` オプションを使ってドリルダウンを並行して実行したときにGroongaがクラッシュすることがある問題を修正しました。

> - [select] `--filter` に非常に長い式を指定するとシンタックスエラーになる問題を修正しました。

[12.0.4リリース - 2022-06-06]

> - 検索実行中に `request_cancel` を実行した時Groongaの応答が遅くなることがある問題を修正しました。

> - 文字列リストをint32のベクターにキャストできない問題を修正しました。

> - GroongaのMuninプラグインがAlmaLinux 8 とCentOS 7上で動作しない問題を修正しました。

[12.0.3リリース - 2022-04-29]

> - パトリシアトライのテーブルにキーを追加できなくなることがある問題を修正しました。

### 感謝

- 篠田さん

- i10aさん

- naoaさん

- shinononさん

- Zhanzhao (Deo) Liangさん

- David CARLIERさん

## 12.1.2リリース - 2023-01-29

### 改良

- [httpd] バンドルしているnginxのバージョンを1.23.3に更新しました。

## 12.1.1リリース - 2023-01-06

### 改良

- [select][POWER_SET] ドリルダウンでベクターのべき集合を集計できるようになりました。

  ドリルダウンに 新しいオプション `key_vector_expansion` を追加しました。 `key_vector_expansion` は、ドリルダウン対象のキーがベクターのときに、キーの展開方法を指定します。 現状は、`key_vector_expansion` には `NONE` または `POWER_SET` が指定できます。

  `key_vector_expansion` に `POWER_SET` を指定することで、べき集合での集計ができるようになります。 この集計方法は、例えばタグの出現回数と、タグの組み合わせの出現回数を一度に集計したい場合に便利です。

  以下は、 `Groonga` 、 `Mroonga` 、 `PGroonga` という３つのタグに対して、これらのタグの出現回数と、 これらの組み合わせの出現回数を集計するケースを考えます。

  実行例:

      table_create PowersetDrilldownMemos TABLE_HASH_KEY ShortText
      # [[0, 1337566253.89858, 0.000355720520019531], true]
      column_create PowersetDrilldownMemos tags COLUMN_VECTOR ShortText
      # [[0, 1337566253.89858, 0.000355720520019531], true]
      load --table PowersetDrilldownMemos
      [
      {"_key": "Groonga is fast!", "tags": ["Groonga"]},
      {"_key": "Mroonga uses Groonga!", "tags": ["Groonga", "Mroonga"]},
      {"_key": "PGroonga uses Groonga!", "tags": ["Groonga", "PGroonga"]},
      {"_key": "Mroonga and PGroonga are Groonga family", "tags": ["Groonga", "Mroonga", "PGroonga"]}
      ]
      # [[0, 1337566253.89858, 0.000355720520019531], 4]
      select PowersetDrilldownMemos \
        --drilldowns[tags].keys tags \
        --drilldowns[tags].key_vector_expansion POWER_SET \
        --drilldowns[tags].columns[power_set].stage initial \
        --drilldowns[tags].columns[power_set].value _key \
        --drilldowns[tags].columns[power_set].flags COLUMN_VECTOR \
        --drilldowns[tags].sort_keys 'power_set' \
        --drilldowns[tags].output_columns 'power_set, _nsubrecs' \
        --limit 0
      # [
      #   [
      #     0,
      #     1337566253.89858,
      #     0.000355720520019531
      #   ],
      #   [
      #     [
      #       [
      #         4
      #       ],
      #       [
      #         [
      #           "_id",
      #           "UInt32"
      #         ],
      #         [
      #           "_key",
      #           "ShortText"
      #         ],
      #         [
      #           "tags",
      #           "ShortText"
      #         ]
      #       ]
      #     ],
      #     {
      #       "tags": [
      #         [
      #           7
      #         ],
      #         [
      #           [
      #             "power_set",
      #             "Text"
      #           ],
      #           [
      #             "_nsubrecs",
      #             "Int32"
      #           ]
      #         ],
      #         [
      #           [
      #             "Groonga"
      #           ],
      #           4
      #         ],
      #         [
      #           [
      #             "Mroonga"
      #           ],
      #           2
      #         ],
      #         [
      #           [
      #             "PGroonga"
      #           ],
      #           2
      #         ],
      #         [
      #           [
      #             "Groonga",
      #             "Mroonga"
      #           ],
      #           2
      #         ],
      #         [
      #           [
      #             "Groonga",
      #             "PGroonga"
      #           ],
      #           2
      #         ],
      #         [
      #           [
      #             "Mroonga",
      #             "PGroonga"
      #           ],
      #           1
      #         ],
      #         [
      #           [
      #             "Groonga",
      #             "Mroonga",
      #             "PGroonga"
      #           ],
      #           1
      #         ]
      #       ]
      #     }
      #   ]
      # ]

  この集計結果から、以下のことがわかります。

  タグ | 登場回数
  `Groonga` | 4
  `Mroonga` | 2
  `PGroonga` | 2
  `Groonga` かつ `Mroonga` | 2
  `Groonga` かつ `PGroonga` | 2
  `Mroonga` かつ `PGroonga` | 1
  `Groonga` かつ `Mroonga` かつ `PGroonga` | 1

  複雑な機能なので、 POWER_SET も合わせて参照してください。

- [select] ベクターカラムの特定の要素のみを対象に検索できるようになりました。

  `match_columns` にベクターカラムの特定の要素をインデックス番号で指定することで、ベクターカラムの特定の要素のみを対象に検索できるようになりました。

  以下はこの機能の例です。

      table_create Memos TABLE_NO_KEY
      column_create Memos contents COLUMN_VECTOR ShortText

      table_create Lexicon TABLE_PAT_KEY ShortText --default_tokenizer TokenBigram
      column_create Lexicon memo_index COLUMN_INDEX|WITH_POSITION|WITH_SECTION Memos contents
      load --table Memos
      [
      ["contents"],
      [["I like Groonga", "Use Groonga with Ruby"]],
      [["I like Ruby", "Use Groonga"]]
      ]
      select Memos \
        --match_columns "contents[1]" \
        --query Ruby \
        --output_columns "contents, _score"
      # [
      #   [
      #     0,
      #     0.0,
      #     0.0
      #   ],
      #   [
      #     [
      #       [
      #         1
      #       ],
      #       [
      #         [
      #           "contents",
      #           "ShortText"
      #         ],
      #         [
      #           "_score",
      #           "Int32"
      #         ]
      #       ],
      #       [
      #         [
      #           "I like Groonga",
      #           "Use Groonga with Ruby"
      #         ],
      #         1
      #       ]
      #     ]
      #   ]
      # ]

  `--match_columns "contents[1]"` とすることで、 `contents` ベクターの第2要素のみを `--query` の対象にしています。この例では、 `["I like Groonga", "Use Groonga with Ruby"]` は第2要素 `Use Groonga with Ruby` に `Ruby` を含むのでヒットしていますが、 `["I like Ruby", "Use Groonga"]` は第2要素 `Use Groonga` に `Ruby` を含まないのでヒットしていません。

- [load] `YYYY-MM-DD` 形式をサポートしました。

  `YYYY-MM-DD` は一般的な時間形式です。この形式をサポートしたことで、 `load` がより使いやすくなりました。

  ロードされた値の時間部分は、現地時間の `00:00:00` になります。

      plugin_register functions/time
      # [[0,0.0,0.0],true]
      table_create Logs TABLE_NO_KEY
      # [[0,0.0,0.0],true]
      column_create Logs created_at COLUMN_SCALAR Time
      # [[0,0.0,0.0],true]
      column_create Logs created_at_text COLUMN_SCALAR ShortText
      # [[0,0.0,0.0],true]
      load --table Logs
      [
      {"created_at": "2000-01-01", "created_at_text": "2000-01-01"}
      ]
      # [[0,0.0,0.0],1]
      select Logs --output_columns "time_format_iso8601(created_at), created_at_text"
      # [
      #   [
      #     0,
      #     0.0,
      #     0.0
      #   ],
      #   [
      #     [
      #       [
      #         1
      #       ],
      #       [
      #         [
      #           "time_format_iso8601",
      #           null
      #         ],
      #         [
      #           "created_at_text",
      #           "ShortText"
      #         ]
      #       ],
      #       [
      #         "2000-01-01T00:00:00.000000+09:00",
      #         "2000-01-01"
      #       ]
      #     ]
      #   ]
      # ]

### 修正

- [select] `command_version` が `3` のとき、 `drilldown` の結果のラベルが不正になる問題を修正しました。 [groonga-dev,05005][篠田さんの報告]

  以下はこの機能の例です。

      table_create Documents TABLE_NO_KEY
      column_create Documents tag1 COLUMN_SCALAR ShortText
      column_create Documents tag2 COLUMN_SCALAR ShortText
      load --table Documents
      [
      {"tag1": "1", "tag2": "2"}
      ]
      select Documents --drilldown tag1,tag2 --command_version 3
      # {
      #   "header": {
      #     "return_code": 0,
      #     "start_time": 1672123380.653039,
      #     "elapsed_time": 0.0005846023559570312
      #   },
      #   "body": {
      #     "n_hits": 1,
      #     "columns": [
      #       {
      #         "name": "_id",
      #         "type": "UInt32"
      #       },
      #       {
      #         "name": "tag1",
      #         "type": "ShortText"
      #       },
      #       {
      #         "name": "tag2",
      #         "type": "ShortText"
      #       }
      #     ],
      #     "records": [
      #       [
      #         1,
      #         "1",
      #         "2"
      #       ]
      #     ],
      #     "drilldowns": {
      #       "ctor": {
      #         "n_hits": 1,
      #         "columns": [
      #           {
      #             "name": "_key",
      #             "type": "ShortText"
      #           },
      #           {
      #             "name": "_nsubrecs",
      #             "type": "Int32"
      #           }
      #         ],
      #         "records": [
      #           [
      #             "1",
      #             1
      #           ]
      #         ]
      #       },
      #       "tag2": {
      #         "n_hits": 1,
      #         "columns": [
      #           {
      #             "name": "_key",
      #             "type": "ShortText"
      #           },
      #           {
      #             "name": "_nsubrecs",
      #             "type": "Int32"
      #           }
      #         ],
      #         "records": [
      #           [
      #             "2",
      #             1
      #           ]
      #         ]
      #       }
      #     }
      #   }
      # }

  `select` の実行結果の `drilldowns` 直後の `ctor` は、本来 `tag1` であるべきです。 この例では `tag1` ではなく `ctor` という値になっていますが、どのような値になるかは不定です。

- [NormalizerTable] 特定の定義が `NormalizerTable` に存在する場合、Groongaがクラッシュすることがある問題を修正しました。 [GitHub:pgroonga/pgroonga#279][i10aさんの報告]

  以下の例を考えます。

      table_create Normalizations TABLE_PAT_KEY ShortText --normalizer NormalizerNFKC130
      column_create Normalizations normalized COLUMN_SCALAR ShortText
      load --table Normalizations
      [
      {"_key": "Ⅰ", "normalized": "1"},
      {"_key": "Ⅱ", "normalized": "2"},
      {"_key": "Ⅲ", "normalized": "3"}
      ]
      normalize 'NormalizerTable("normalized", "Normalizations.normalized")'   "ⅡⅡ"

  この問題は、以下の1.、2.、3.の条件を満たした時に発生します。

  1. 対象となるテーブルのキーがノーマライズされる

     この例では、 `Normalizations` に `--normalizer NormalizerNFKC130` が指定されているので、この条件を満たしています。`Ⅰ` 、 `Ⅱ` 、 `Ⅲ` はそれぞれ `NormalizerNFKC130` によって `i` 、 `ii` 、 `iii` にノーマライズされます。

  2. ノーマライズされた文字列に他のノーマライズされた文字列が含まれている

     上記のノーマライズ後の値を考えると、 `iii` が `ii` と `i` を含んでいるため、条件を満たしています。`ii` は `i` それぞれノーマライズ前の `Ⅱ` と `Ⅰ` に対応します。

  3. 2.の文字列を複数使用する

     `normaize` の対象である `ⅡⅡ` は `NormalizerNFKC130` によって `iiii` にノーマライズされます。 この値に対して、 `Normalizations` の `NormalizerNFKC130` によるノーマライズ後の値が一致条件として使用されてノーマライズされます。

     したがって、 `iiii` を `Normalizations` でノーマライズしようとするときには、以下の順番でノーマライズされるため、この条件を満たしています。

     - 最初の `iii` （ `Ⅲ` に対応）

       NormalizerTable は最長共通接頭辞探索を行うため、 最初は `ii` や `i` ではなく `iii` が使用されます。

     - 残りの `i` （ `Ⅰ` に対応）

### 感謝

- i10aさん

- 篠田さん

## 12.1.0 リリース - 2022-11-29

### 改良

- [load] `load` のスローログの出力に対応しました。

  この機能は、Groongaのパフォーマンスチューニングに使用します。例えば、 `load` が遅いときに、この機能を使うことで平均よりも時間がかかっているレコードを検出できます。

  環境変数 `GRN_SLOW_LOG_THRESHOLD` を指定することで、スローログの出力が有効になります。

  `GRN_SLOW_LOG_THRESHOLD` については以下のとおりです。

  - `GRN_SLOW_LOG_THRESHOLD` にはしきい値となる時間を秒単位で指定します。小数を指定することで、1秒よりも短い時間も指定できます。

  - `GRN_SLOW_LOG_THRESHOLD` で指定された時間よりも時間がかかっている処理がある場合、デバッグレベルのログが出力されます。

  ログレベルの設定は `log-level` オプションまたは log_level コマンドで変更可能です。

  `GRN_SLOW_LOG_THRESHOLD` にどのような値を指定すべきかは環境や調べたい内容に依存します。例えば、 `load` の件数と所要時間から、1レコードあたりの所要時間を求め、その値を指定することが考えられます。こうすることで、平均よりも `load` に時間がかかっているレコードを調べることができます。

  `load` の所要時間は クエリーログ から確認することができます。

      2022-11-16 16:41:27.139000|000000CE63AFF640|>load --table Memo
      2022-11-16 16:43:40.841000|000000CE63AFF640|:000133702000000 load(100000): [0][0][100000]
      2022-11-16 16:43:40.842000|000000CE63AFF640|:000133703000000 send(46)
      2022-11-16 16:43:40.842000|000000CE63AFF640|<000133703000000 rc=0

  この例では、所要時間は以下のようになっています。

  - レコード数: 100000件

  - 所要時間: 2分13秒 = 133秒 （ `load` の開始時間 16:43:27 と `load` の終了時間（ `rc=0` ）16:43:40 に基づいています。 ）

  - 1行あたりの所要時間: 0.00133 秒

  したがって、どのレコードが時間がかかっているのか調べるためには、 `GRN_SLOW_LOG_THRESHOLD` に `0.00133` を指定します。

  スローログを有効化すると以下の悪影響があることに注意してください。

  - パフォーマンスの悪化

  - ログサイズの肥大化

  そのため、必要な場合にのみこのスローログを有効にすることを推奨します。

- [API] 新しいAPI `grn_is_reference_count_enable()` を追加しました。

  参照カウントモードが有効になっているかどうかの真偽値を返却します。

- [API] 新しいAPI `grn_set_reference_count_enable(bool enable)` を追加しました。

  参照カウントモードの有効/無効を切り替えます。

  安全のため、複数のテーブルを開いている場合は参照カウントモードを切り替えません。

- [API] 新しいAPI `grn_is_back_trace_enable()` を追加しました。

  バックトレースの出力が有効になっているかどうかの真偽値を返却します。

- [API] 新しいAPI `grn_set_back_trace_enable(bool enable)` を追加しました。

  バックトレース(back trace)の出力の有効/無効を切り替えます。

  バックトレースの出力時にクラッシュする環境があるため、その環境では無効化します。

- [status] 新しい項目 `back_trace` と `reference_count` を追加しました。

  `back_trace` はバックトレースの出力が有効になっているかどうかを真偽値で返却します。

  `reference_count` は参照カウントモードが有効になっているかどうかを真偽値で返却します。

      status
      [
        [
          0,
          1654237168.304533,
          0.0001480579376220703
        ],
        {
          (omitted)
          "back_trace": true,
          "reference_count": false,
        }
      ]

### 修正

- [select][ベクターカラム] 重み付きベクターカラムで `WEIGHT_FLOAT32` を指定したとき、結果が整数で表示されていた問題を修正しました。

  参照型の重み付きベクターカラムにはこの問題はなく、参照型ではない重み付きベクターカラムにだけこの問題がありました。

  内部的な処理は浮動小数点数で行われていましたが、最終的な結果の表示が整数になっていました。

  以下は、この問題の例です。

      table_create Memos TABLE_HASH_KEY ShortText
      # [[0,0.0,0.0],true]
      column_create Memos tags COLUMN_VECTOR|WITH_WEIGHT|WEIGHT_FLOAT32 ShortText
      # [[0,0.0,0.0],true]
      load --table Memos
      [
      {
        "_key": "Groonga is fast",
        "tags": {
          "groonga": 2.8,
          "full text search": 1.2
        }
      }
      ]
      # [[0,0.0,0.0],1]
      select Memos
      # [
      #   [
      #     0,
      #     0.0,
      #     0.0
      #   ],
      #   [
      #     [
      #       [
      #         1
      #       ],
      #       [
      #         [
      #           "_id",
      #           "UInt32"
      #         ],
      #         [
      #           "_key",
      #           "ShortText"
      #         ],
      #         [
      #           "tags",
      #           "ShortText"
      #         ]
      #       ],
      #       [
      #         1,
      #         "Groonga is fast",
      #         {
      #           "groonga": 2,
      #           "full text search": 1
      #         }
      #       ]
      #     ]
      #   ]
      # ]

  `tags` カラムが `ShortText` 型の重み付きベクターカラム、つまり参照型でない重み付きベクターカラムです。

  この例の `select` の結果の以下の部分は、それぞれ2.8、1.2であるべきですが、2、1と誤った結果が返却されていました。

      {
        "groonga": 2,
        "full text search": 1
      }

  この修正により、以下のように正しい結果が返却されるようになりました。

      select Memos
      # [
      #   [
      #     0,
      #     0.0,
      #     0.0
      #   ],
      #   [
      #     [
      #       [
      #         1
      #       ],
      #       [
      #         [
      #           "_id",
      #           "UInt32"
      #         ],
      #         [
      #           "_key",
      #           "ShortText"
      #         ],
      #         [
      #           "tags",
      #           "ShortText"
      #         ]
      #       ],
      #       [
      #         1,
      #         "Groonga is fast",
      #         {
      #           "groonga": 2.8,
      #           "full text search": 1.2
      #         }
      #       ]
      #     ]
      #   ]
      # ]

## 12.0.9リリース - 2022-10-28

### 改良

- [AlmaLinux] AlmaLinux 9 向けのパッケージをサポートしました。

  12.0.8リリース - 2022-10-03 でサポートしていましたが、アナウンスしていませんでした。

- [escalate] `escalate()` 関数のドキュメントを追加しました。

- [ノーマライザー] `NormalizerHTML` を追加しました。（実験的）

  `NormalizerHTML` はHTML用のノーマライザーです。

  現在 `NormalizerHTML` は `<span>` や `</span>` といったタグの削除と、`&amp;` や `&#38;` といった文字参照の展開を行います。

  以下は `NormalizerHTML` の例です。

      normalize NormalizerHTML "<span> Groonga &amp; Mroonga &#38; Rroonga </span>"
      [[0,1666923364.883798,0.0005481243133544922],{"normalized":" Groonga & Mroonga & Rroonga ","types":[],"checks":[]}]

  この例では、 `<span>` と `</span>` は削除され、 `&amp;` と `&#38;` は `&` に展開されています。

  タグを削除するかどうかは `remove_tag` オプションで指定できます。(`remove_tag` オプションのデフォルト値は `true` です。)

      normalize 'NormalizerHTML("remove_tag", false)' "<span> Groonga &amp; Mroonga &#38; Rroonga </span>"
      [[0,1666924069.278549,0.0001978874206542969],{"normalized":"<span> Groonga & Mroonga & Rroonga </span>","types":[],"checks":[]}]

  この例では、 `<span>` と `</span>` は削除されていません。

  文字参照を展開するかどうかは `expand_character_reference` オプションで指定できます。(`expand_character_reference` オプションのデフォルト値は `true` です。)

      normalize 'NormalizerHTML("expand_character_reference", false)' "<span> Groonga &amp; Mroonga &#38; Rroonga </span>"
      [[0,1666924357.099782,0.0002346038818359375],{"normalized":" Groonga &amp; Mroonga &#38; Rroonga ","types":[],"checks":[]}]

  この例では、 `&amp;` と `&#38;` は展開されていません。

- [httpd] バンドルしているnginxのバージョンを1.23.2に更新しました。

  CVE-2022-41741とCVE-2022-41742のセキュリティの修正が含まれています。これらのセキュリティーの修正の詳細については、https://nginx.org/en/CHANGES を参照してください。

- メモリーが不足した際に、同じログが大量に出力されないように変更しました。

  メモリーが不足した際に、 `mmap failed!!!!` というメッセージが大量にログが記載されることがありました。このメッセージを可能な限り重複してログ出力されないように改良しました。

### 修正

- [select] n_workers を指定したとき、Groongaがクラッシュしたり、誤った結果を返すことがある問題を修正しました。

  この問題は、 n_workers に `1` より大きい値を指定し、かつ同時に `drilldowns[{LABEL}].filter` を使用している場合に発生していました。

  この問題は内部的な並列処理の際に、誤った値（オブジェクト）を参照していたことが原因で発生していました。そのため、上記の条件が満たされたとき、内部的に並列処理のタイミングによって、Groongaがクラッシュしたり誤った値を返すことがありました。

## 12.0.8リリース - 2022-10-03

### 改良

- `escalate()` 関数（実験的）の仕様を使いやすいように変更しました。

  `escalate()` の外部の結果セットを使用しないように変更しました。

  前回の仕様では、ユーザーはどのくらいの結果が `escalate()` に渡されるのか推測して最初のしきい値を決める必要があり、不便でした。

  以下は前回の `escalate()` の例です。

      number_column > 10 && escalate(THRESHOLD_1, CONDITION_1,
                                     ...,
                                     THRESHOLD_N, CONDITION_N)

  `CONDITION1` は `number_column > 10` の結果が `THRESHOLD_1` 以下の時に実行されます。ユーザーは `THRESHOLD_1` を決めるのに `number_column > 10` がどのくらいの結果を返すのか推測する必要がありました。

  今回のリリースから、ユーザーが `number_column > 10` がどのくらいの結果を返すのか推測する必要がなくなり、使いやすくなりました。

  この変更により、 `escalate()` の構文が以下の通り変更されています。

  前回の構文

      escalate(THRESHOLD_1, CONDITION_1,THRESHOLD_2, CONDITION_2, ..., THRESHOLD_N, CONDITION_N)

  新しい構文

      escalate(CONDITION_1, THRESHOLD_2, CONDITION_2, ..., THRESHOLD_N, CONDITION_N)

  以下は構文の変更の詳細です。

  - 最初の条件のためのしきい値は不要となりました。

  - 引数の指定を必須としました。最初の条件が必須となります。

  - 最初の引数を常に実行します。

  この関数は実験的な関数です。将来的にこれらの動作は変更になる可能性があります。

- [CMakeを使ってGroongaをビルドする方法] CMakeを使ってビルドする方法を追加しました。

- [その他] GNU Autotoolsを使ってビルドする場合に、Apache Arrowの機能を有効化/無効化する方法について追加しました。

- [select] drilldowns[${LABEL}].table のドキュメントを追加しました。

- [国際化] 翻訳方法を更新しました。

### 修正

- NormalizerTable で冪等でない（繰り返し実行すると結果が変わることがある）定義をした時に、Groongaが誤った結果を返すことがある問題を修正しました。

  これは、検索する値について、値を受け取った後と、トークナイズした後の二回ノーマライズしていたことが原因です。

  Groongaはレコードを追加する時に、インデックス用のテーブルに設定したトークナイザーとノーマライザーを使って、登録するデータをトークナイズしてからノーマライズしています。検索する値についても、インデックス用のテーブルに設定したトークナイザーとノーマライザーを使って、トークナイズしてからノーマライズして、その後インデックスと照合します。両者は同じトークナイザーとノーマライザーを使うので、検索する値がインデックスに登録したデータと同じであれば、インデックスに格納されている状態と同じ状態になります。

  しかし、いままでGroongaは検索する値だけを余分にノーマライズしていました。

  NormalizerAuto といった組み込みのノーマライザーは冪等である（繰り返し実行しても結果が変わらない）ため、この問題は発生しません。一方で、 NormalizerTable はユーザー自身がノーマライザーの定義をすることができます。そのため、冪等でない（繰り返し実行すると結果が変わることがある）定義をすることができました。

  NormalizerTable に冪等でない定義が存在する場合、検索する値のみが余分にノーマライズされることで、インデックスに登録したデータと検索する値が一致しない場合がありました。

  そのような場合、ヒットするはずのデータがヒットしなかったり、ヒットしないはずのデータがヒットしたりしていました。

  以下はこの問題の例です。

      table_create ColumnNormalizations TABLE_NO_KEY
      column_create ColumnNormalizations target_column COLUMN_SCALAR ShortText
      column_create ColumnNormalizations normalized COLUMN_SCALAR ShortText

      load --table ColumnNormalizations
      [
      {"target_column": "a", "normalized": "b"},
      {"target_column": "b", "normalized": "c"}
      ]

      table_create Targets TABLE_PAT_KEY ShortText
      column_create Targets column_normalizations_target_column COLUMN_INDEX \
        ColumnNormalizations target_column

      table_create Memos TABLE_NO_KEY
      column_create Memos content COLUMN_SCALAR ShortText

      load --table Memos
      [
      {"content":"a"},
      {"content":"c"},
      ]

      table_create \
        Terms \
        TABLE_PAT_KEY \
        ShortText \
        --default_tokenizer 'TokenNgram' \
        --normalizers 'NormalizerTable("normalized", \
                                      "ColumnNormalizations.normalized", \
                                      "target", \
                                      "target_column")'

      column_create Terms memos_content COLUMN_INDEX|WITH_POSITION Memos content

      select Memos --query content:@a
      [[0,1664781132.892326,0.03527212142944336],[[[1],[["_id","UInt32"],["content","ShortText"]],[2,"c"]]]]

  `select Memos --query content:@a` の結果の期待値は `a` ですが、Groongaは `c` を返していました。これは、入力された `a` が `ColumnNormalizations` の定義にしたがって `b` にノーマライズされ、その後、 ノーマライズされた `b` を更に `c` にノーマライズしていたためです。結果的に、入力された `a` は `c` に変換され、 `Memos` テーブルの `{"content":"c"}` にマッチしていました。

## 12.0.7リリース - 2022-08-29

### 改良

- 新しい関数 `escalate()` を追加しました。(実験的)

  `escalate()` 関数は既存のマッチエスカレーション( 検索 )と似ています。この関数は、全ての条件で使えます。（既存のマッチエスカレーションは、一つの転置インデックスによる全文検索で使えます。）

  `escalate()` 関数は検索結果の数を制限したい時に便利です。検索結果の数の制限は、 `--limit` でもできますが、 `--limit` は全ての条件を評価した後に評価されます。`escalate()` 関数は結果セットが `THRESHOLD` より多くのレコードを持っていたら、その時点で評価を終了します。つまり、 `escalate()` 関数は条件の評価の数を減らせる可能性があります。

  `escalate()` の構文は以下の通りです。

      escalate(THRESHOLD_1, CONDITION_1,
               THRESHOLD_2, CONDITION_2,
               ...,
               THRESHOLD_N, CONDITION_N)

  `THRESHOLD_N` は、0や29のような正の数です。 `CONDITION_N` は `number_column > 29` のような スクリプト構文 を使った文字列です。

  現在の結果セットのレコード数が `THRESHOLD_1` 以下の場合、 `CONDITION_1` が実行されます。同様に、 `CONDITION_1` 評価後の結果セットのレコード数が `THRESHOLD_2` 以下の場合、 `CONDITION_2` が実行されます。 `CONDITION_2` 評価後の結果セットのレコード数が `THRESHOLD_3` より大きい場合、 `escalate()` は終了します。

  全ての `CONDITION` が実行された場合、 `escalate(THRESHOLD_1, CONDITION_1, ..., THRESHOLD_N, CONDITION_N)` は `CONDITION_1 || ... || CONDITION_N` と同じです。

  `escalate()` 関数は、 `&&` and `&!` のような論理演算子と一緒に使えます。:

      number_column > 10 && escalate(THRESHOLD_1, CONDITION_1,
                                     ...,
                                     THRESHOLD_N, CONDITION_N)
      number_column > 10 &! escalate(THRESHOLD_1, CONDITION_1,
                                     ...,
                                     THRESHOLD_N, CONDITION_N)

  これらは、 `number_column > 10 && (CONDITION_1 || ... || CONDITION_N)` と `number_column > 10 &! (CONDITION_1 || ... || CONDITION_N)` と同じです。

  しかし、これらの挙動は使いにくいため変更される可能性があります。

- [httpd] バンドルしているnginxのバージョンを1.23.1に更新しました。

- [select] `--n_workers` オプションのドキュメントを追加しました。

### 修正

- OR検索実行中に `request_cancel` を実行した場合、Groongaの応答が遅くなることがある問題を修正しました。

  OR検索の結果が多い場合や多くのOR条件をもつクエリー場合に、 "request_cancel" コマンドが原因でGroongaのレスポンスが遅くなることがあります。

## 12.0.6リリース - 2022-08-04

### 改良

- groonga-delta用の新しいMuninプラグインを追加しました。

  このプラグインによって、以下の項目を監視できます。

  > - `groonga-delta-import` がローカルのストレージ上の `.grn` ファイルをインポートできているかどうか。

  > - `groonga-delta-import` がMySQLの差分データをインポートできているかどうか。

  > - `groonga-delta-apply` がインポートしたデータを適用できているかどうか。

  > - 適用したデータの総サイズ。

- [column_copy] 重み付きベクターをサポートしました。

  以下のように、重み付きベクターの値を `column_copy` でコピーできます。

      table_create Tags TABLE_HASH_KEY ShortText
      [[0,0.0,0.0],true]
      table_create CopyFloat32Value TABLE_HASH_KEY ShortText
      [[0,0.0,0.0],true]
      column_create CopyFloat32Value source_tags COLUMN_VECTOR|WITH_WEIGHT|WEIGHT_FLOAT32 Tags
      [[0,0.0,0.0],true]
      column_create CopyFloat32Value destination_tags COLUMN_VECTOR|WITH_WEIGHT|WEIGHT_FLOAT32 Tags
      [[0,0.0,0.0],true]
      load --table CopyFloat32Value
      [
      {
        "_key": "Groonga is fast!!!",
        "source_tags": {
          "Groonga": 2.8,
          "full text search": 1.5
        }
      }
      ]
      [[0,0.0,0.0],1]
      column_copy CopyFloat32Value source_tags CopyFloat32Value destination_tags
      [[0,0.0,0.0],true]
      select CopyFloat32Value
      [
        [
          0,
          0.0,
          0.0
        ],
        [
          [
            [
              1
            ],
            [
              [
                "_id",
                "UInt32"
              ],
              [
                "_key",
                "ShortText"
              ],
              [
                "destination_tags",
                "Tags"
              ],
              [
                "source_tags",
                "Tags"
              ]
            ],
            [
              1,
              "Groonga is fast!!!",
              {
                "Groonga": 2.8,
                "full text search": 1.5
              },
              {
                "Groonga": 2.8,
                "full text search": 1.5
              }
            ]
          ]
        ]
      ]

- [Ubuntu] Ubuntu 21.10 (Impish Indri) のサポートをやめました。

  Ubuntu 21.10 は、2022年7月でEOLとなったためです。

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

  Debian 10 は、2022年8月でEOLとなるためです。

### 修正

- `n_workers` オプションを使ってドリルダウンを並行して実行したときにGroongaがクラッシュすることがある問題を修正しました。

- [select] `--filter` に非常に長い式を指定するとシンタックスエラーになる問題を修正しました。

  今まで `--filter` 用のスタックサイズを100にしていたため発生していました。

## 12.0.5リリース - 2022-06-29

### 改良

- [select] 検索エスカレーションによる前方一致検索のパフォーマンスを少し改善しました。

- [select] `drilldowns[LABEL]._key` に重み付き参照ベクターカラムを指定できるようになりました。 [GitHub#1366][naoaさんがパッチ提供]

  今までは、ドリルダウンのキーに重み付き参照ベクターカラムを指定すると、Groongaが誤った結果を返していました。

  例えば、以下のタグ検索は、今まで誤った結果を返していました。

      table_create Tags TABLE_PAT_KEY ShortText

      table_create Memos TABLE_HASH_KEY ShortText
      column_create Memos tags COLUMN_VECTOR|WITH_WEIGHT Tags
      column_create Memos date COLUMN_SCALAR Time

      load --table Memos
      [
      {"_key": "Groonga is fast!", "tags": {"full-text-search": 100}, "date": "2014-11-16 00:00:00"},
      {"_key": "Mroonga is fast!", "tags": {"mysql": 100, "full-text-search": 80}, "date": "2014-11-16 00:00:00"},
      {"_key": "Groonga sticker!", "tags": {"full-text-search": 100, "sticker": 10}, "date": "2014-11-16 00:00:00"},
      {"_key": "Rroonga is fast!", "tags": {"full-text-search": 100, "ruby": 20}, "date": "2014-11-17 00:00:00"},
      {"_key": "Groonga is good!", "tags": {"full-text-search": 100}, "date": "2014-11-17 00:00:00"}
      ]

      select Memos \
        --drilldowns[tags].keys tags \
        --drilldowns[tags].output_columns _key,_nsubrecs
      [
        [
          0,
          1656480220.591901,
          0.0005342960357666016
        ],
        [
          [
            [
              5
            ],
            [
              [
                "_id",
                "UInt32"
              ],
              [
                "_key",
                "ShortText"
              ],
              [
                "date",
                "Time"
              ],
              [
                "tags",
                "Tags"
              ]
            ],
            [
              1,
              "Groonga is fast!",
              1416063600.0,
              {"full-text-search":100}
            ],
            [
              2,
              "Mroonga is fast!",
              1416063600.0,
              {"mysql":100,"full-text-search":80}
            ],
            [
              3,
              "Groonga sticker!",
              1416063600.0,
              {"full-text-search":100,"sticker":10}
            ],
            [
              4,
              "Rroonga is fast!",
              1416150000.0,
              {"full-text-search":100,"ruby":20}
            ],
            [
              5,
              "Groonga is good!",
              1416150000.0,
              {"full-text-search":100}
            ]
          ],
          {
            "tags": [
              [
                8
              ],
              [
                [
                  "_key",
                  "ShortText"
                ],
                [
                  "_nsubrecs",
                  "Int32"
                ]
              ],
              [
                "full-text-search",
                5
              ],
              [
                "f",
                5
              ],
              [
                "mysql",
                1
              ],
              [
                "f",
                1
              ],
              [
                "sticker",
                1
              ],
              [
                "f",
                1
              ],
              [
                "ruby",
                1
              ],
              [
                "f",
                1
              ]
            ]
          }
        ]

  今回のリリースから上記のクエリーは、以下のように正しい結果を返します。

      select Memos   --drilldowns[tags].keys tags   --drilldowns[tags].output_columns _key,_nsubrecs
      [
        [
          0,
          0.0,
          0.0
        ],
        [
          [
            [
              5
            ],
            [
              [
                "_id",
                "UInt32"
              ],
              [
                "_key",
                "ShortText"
              ],
              [
                "date",
                "Time"
              ],
              [
                "tags",
                "Tags"
              ]
            ],
            [
              1,
              "Groonga is fast!",
              1416063600.0,
              {
                "full-text-search": 100
              }
            ],
            [
              2,
              "Mroonga is fast!",
              1416063600.0,
              {
                "mysql": 100,
                "full-text-search": 80
              }
            ],
            [
              3,
              "Groonga sticker!",
              1416063600.0,
              {
                "full-text-search": 100,
                "sticker": 10
              }
            ],
            [
              4,
              "Rroonga is fast!",
              1416150000.0,
              {
                "full-text-search": 100,
                "ruby": 20
              }
            ],
            [
              5,
              "Groonga is good!",
              1416150000.0,
              {
                "full-text-search": 100
              }
            ]
          ],
          {
            "tags": [
              [
                4
              ],
              [
                [
                  "_key",
                  "ShortText"
                ],
                [
                  "_nsubrecs",
                  "Int32"
                ]
              ],
              [
                "full-text-search",
                5
              ],
              [
                "mysql",
                1
              ],
              [
                "sticker",
                1
              ],
              [
                "ruby",
                1
              ]
            ]
          }
        ]
      ]

- [select] `query` や `filter` や `post_filter` を使っていても、ドリルダウンのキーに重み付き参照ベクターカラムを指定できるようになりました。 [GitHub#1367][naoaさんがパッチ提供]

  今までは、 `query` や `filter` や `post_filter` を使っているときに、ドリルダウンのキーに重み付き参照ベクターカラムを指定するとGroongaは誤った結果、またはエラーを返していました。

  例えば、今まで以下のクエリーはエラーを返していました。

      table_create Tags TABLE_PAT_KEY ShortText

      table_create Memos TABLE_HASH_KEY ShortText
      column_create Memos tags COLUMN_VECTOR|WITH_WEIGHT Tags
      column_create Memos date COLUMN_SCALAR Time

      load --table Memos
      [
      {"_key": "Groonga is fast!", "tags": {"full-text-search": 100}, "date": "2014-11-16 00:00:00"},
      {"_key": "Mroonga is fast!", "tags": {"mysql": 100, "full-text-search": 80}, "date": "2014-11-16 00:00:00"},
      {"_key": "Groonga sticker!", "tags": {"full-text-search": 100, "sticker": 10}, "date": "2014-11-16 00:00:00"},
      {"_key": "Rroonga is fast!", "tags": {"full-text-search": 100, "ruby": 20}, "date": "2014-11-17 00:00:00"},
      {"_key": "Groonga is good!", "tags": {"full-text-search": 100}, "date": "2014-11-17 00:00:00"}
      ]

      select Memos \
        --filter true \
        --post_filter true \
        --drilldowns[tags].keys tags \
        --drilldowns[tags].output_columns _key,_nsubrecs
      [
        [
          -22,
          1656473820.734894,
          0.03771400451660156,
          "[hash][add][           ] key size unmatch",
          [
            [
              "grn_hash_add",
              "hash.c",
              3405
            ]
          ]
        ],
        [
          [
          ]
        ]
      ]

  今回のリリースから上記のクエリーは、以下のように正しい結果を返します。

      select Memos \
        --filter true \
        --post_filter true \
        --drilldowns[tags].keys tags \
        --drilldowns[tags].output_columns _key,_nsubrecs
      [
        [
          0,
          0.0,
          0.0
        ],
        [
          [
            [
              5
            ],
            [
              [
                "_id",
                "UInt32"
              ],
              [
                "_key",
                "ShortText"
              ],
              [
                "date",
                "Time"
              ],
              [
                "tags",
                "Tags"
              ]
            ],
            [
              1,
              "Groonga is fast!",
              1416063600.0,
              {
                "full-text-search": 100
              }
            ],
            [
              2,
              "Mroonga is fast!",
              1416063600.0,
              {
                "mysql": 100,
                "full-text-search": 80
              }
            ],
            [
              3,
              "Groonga sticker!",
              1416063600.0,
              {
                "full-text-search": 100,
                "sticker": 10
              }
            ],
            [
              4,
              "Rroonga is fast!",
              1416150000.0,
              {
                "full-text-search": 100,
                "ruby": 20
              }
            ],
            [
              5,
              "Groonga is good!",
              1416150000.0,
              {
                "full-text-search": 100
              }
            ]
          ],
          {
            "tags": [
              [
                4
              ],
              [
                [
                  "_key",
                  "ShortText"
                ],
                [
                  "_nsubrecs",
                  "Int32"
                ]
              ],
              [
                "full-text-search",
                5
              ],
              [
                "mysql",
                1
              ],
              [
                "sticker",
                1
              ],
              [
                "ruby",
                1
              ]
            ]
          }
        ]
      ]

### 既知の問題

- 現在Groongaには、ベクターカラムに対してデータを大量に追加、削除、更新した際にデータが破損することがある問題があります。

- `*<` と `*>` は、filter条件の右辺に `query()` を使う時のみ有効です。もし、以下のように指定した場合、 `*<` と `*>` は `&&` として機能します。

  > - `'content @ "Groonga" *< content @ "Mroonga"'`

- `GRN_II_CURSOR_SET_MIN_ENABLE` が原因でマッチするはずのレコードを返さないことがあります。

### 感謝

- naoaさん

## 12.0.4リリース - 2022-06-06

### 改良

- [Ubuntu] Ubuntu 22.04 (Jammy Jellyfish)をサポートしました。

- groonga-benchmark の提供をやめました。

  誰も使用しておらず、メンテナンスもできないためです。

- [status] 新しい項目 `memory_map_size` を追加しました。

  `status` コマンドを使うことで、Groongaのメモリーマップサイズの合計を取得できます。

      status
      [
        [
          0,
          1654237168.304533,
          0.0001480579376220703
        ],
        {
          (omitted)
          "memory_map_size": 70098944
        }
      ]

  例えば、Windowsでは、Mroogaが物理メモリーとスワップ領域を使い果たした場合、それ以上メモリーをマップすることができません。そのため、この値を監視することで、メモリーが十分でない環境でもメモリーマップサイズを適切にコントロールできます。

### 修正

- 検索実行中に `request_cancel` を実行した時Groongaの応答が遅くなることがある問題を修正しました。

  特に、検索対象のレコード数が多い時に、Groongaの応答がとても遅くなることがあります。

- 文字列リストをint32のベクターにキャストできない問題を修正しました。

  例えば、以下のキャストは失敗していました。

  - ["10", "100"] -> [10, 100]

  この問題は、 `load` の引数として、 `input_type` に `apache-arrow` を指定したときのみ発生します。 この問題は、Groonga 12.0.2以降で発生します。

- GroongaのMuninプラグインがAlmaLinux 8 とCentOS 7上で動作しない問題を修正しました。

## 12.0.3リリース - 2022-04-29

### 改良

- [logical_count] `logical_count` 実行中のメモリー使用量を改善しました。

  いままで、Groongaは `logical_count` 実行中に確保したオブジェクト(オブジェクトとは、テーブルやカラム、インデックスなどです。)と一時テーブルを `logical_count` の実行完了まで保持し続けていました。

  この機能によって、Groongaは、1つのシャードを処理した後すぐに参照を減らします。そのため、Groongaは、 `logical_count` の実行中にメモリーを解放できるようになり、Groongaのメモリー使用量を削減できることがあります。

  この機能は参照カウントモードのときのみ有効です。`GRN_ENABLE_REFERENCE_COUNT=yes` と設定することで、参照カウントモードを有効にできます。

  加えて、Groongaは、この機能によって `logical_count` 実行中に一時テーブルを動的に解放します。そのため、Groongaのメモリー使用量を削減できます。この改善は、参照カウントモードが有効でなくても効果があります。

- [dump] `MISSING_IGNORE/MISSING_NIL` をサポートしました。

  `MISSING_IGNORE/MISSING_NIL` を持つカラムがある場合、これらのカラムのダンプに失敗していました。このリリースから、 `dump` コマンドはこれらのカラムをサポートしました。

- [snippet],[snippet_html] 入力としてベクターをサポートしました。[groonga-dev,04956][Reported by shinonon]

  例えば、以下のようにJSONデータ内のベクターに対して検索キーワードの周辺テキストを抽出できます。

      table_create Entries TABLE_NO_KEY
      column_create Entries title COLUMN_SCALAR ShortText
      column_create Entries contents COLUMN_VECTOR ShortText

      table_create Tokens TABLE_PAT_KEY ShortText   --default_tokenizer TokenNgram   --normalizer NormalizerNFKC130
      column_create Tokens entries_title COLUMN_INDEX|WITH_POSITION Entries title
      column_create Tokens entries_contents COLUMN_INDEX|WITH_SECTION|WITH_POSITION   Entries contents

      load --table Entries
      [
      {
        "title": "Groonga and MySQL",
        "contents": [
          "Groonga is a full text search engine",
          "MySQL is a RDBMS",
          "Mroonga is a MySQL storage engine based on Groonga"
        ]
      }
      ]

      select Entries\
        --output_columns 'snippet_html(contents), contents'\
        --match_columns 'title'\
        --query Groonga
      [
        [
          0,
          0.0,
          0.0
        ],
        [
          [
            [
              1
            ],
            [
              [
                "snippet_html",
                null
              ],
              [
                "contents",
                "ShortText"
              ]
            ],
            [
              [
                "<span class=\"keyword\">Groonga</span> is a full text search engine",
                "Mroonga is a MySQL storage engine based on <span class=\"keyword\">Groonga</span>"
              ],
              [
                "Groonga is a full text search engine",
                "MySQL is a RDBMS",
                "Mroonga is a MySQL storage engine based on Groonga"
              ]
            ]
          ]
        ]
      ]

  今までも、 `--output_columns 'snippet_html(contents[1])'` のように `snippet*` を指定することで以下のようにベクターに対して検索キーワードの周辺テキストを抽出できますが、この方法ではどの要素を出力すればよいかわかりません。どの要素が検索にヒットしたかわからないためです。

      select Entries\
        --output_columns 'snippet_html(contents[0]), contents'\
        --match_columns 'title'\
        --query Groonga
      [
        [
          0,
          0.0,
          0.0
        ],
        [
          [
            [
              1
            ],
            [
              [
                "snippet_html",
                null
              ],
              [
                "contents",
                "ShortText"
              ]
            ],
            [
              [
                "<span class=\"keyword\">Groonga</span> is a full text search engine"
              ],
              [
                "Groonga is a full text search engine",
                "MySQL is a RDBMS",
                "Mroonga is a MySQL storage engine based on Groonga"
              ]
            ]
          ]
        ]
      ]

- [`vector_join`] 新しい関数 `vector_join()` を追加しました。 [groonga-dev,04956][shinononさんの報告]

  この関数は各要素を結合します。この関数の第二引数で区切り文字を指定できます。

  例えば、以下のようにベクターに対して `snippet()` や `snippet_html()` を実行できます。

      plugin_register functions/vector

      table_create Entries TABLE_NO_KEY
      column_create Entries title COLUMN_SCALAR ShortText
      column_create Entries contents COLUMN_VECTOR ShortText

      table_create Tokens TABLE_PAT_KEY ShortText   --default_tokenizer TokenNgram   --normalizer NormalizerNFKC130
      column_create Tokens entries_title COLUMN_INDEX|WITH_POSITION Entries title
      column_create Tokens entries_contents COLUMN_INDEX|WITH_SECTION|WITH_POSITION   Entries contents

      load --table Entries
      [
      {
        "title": "Groonga and MySQL",
        "contents": [
          "Groonga is a full text search engine",
          "MySQL is a RDBMS",
          "Mroonga is a MySQL storage engine based on Groonga"
        ]
      }
      ]

      select Entries\
        --output_columns 'snippet_html(vector_join(contents, "\n")), contents'\
        --match_columns 'title'\
        --query Groonga --output_pretty yes
      [
        [
          0,
          1650849001.524027,
          0.0003361701965332031
        ],
        [
          [
            [
              1
            ],
            [
              [
                "snippet_html",
                null
              ],
              [
                "contents",
                "ShortText"
              ]
            ],
            [
              [
                "<span class=\"keyword\">Groonga</span> is a full text search engine\nMySQL is a RDBMS\nMroonga is a MySQL storage engine based on <span class=\"keyword\">Groonga</span>"
              ],
              [
                "Groonga is a full text search engine","MySQL is a RDBMS","Mroonga is a MySQL storage engine based on Groonga"
              ]
            ]
          ]
        ]
      ]

- [インデックス構築] 動的インデックス構築のようにとても大きなトークンを無視するようにしました。 [GitHub:pgroonga/pgroonga#209][Zhanzhao (Deo) Liangさんの報告]

  Groongaはエラーを発生しなくなり、静的インデックス構築を実行する時に大きなトークンを無視し警告を出力します。

### 修正

- パトリシアトライのテーブルにキーを追加できなくなることがある問題を修正しました。

  この問題は、以下の条件で発生します。

  - パトリシアトライのテーブルにすでにキーがある場合。

  - 4096バイトのキーを追加する場合。

### 既知の問題

- 現在Groongaには、ベクターカラムに対してデータを大量に追加、削除、更新した際にデータが破損することがある問題があります。

- `*<` と `*>` は、filter条件の右辺に `query()` を使う時のみ有効です。もし、以下のように指定した場合、 `*<` と `*>` は `&&` として機能します。

  > - `'content @ "Groonga" *< content @ "Mroonga"'`

- `GRN_II_CURSOR_SET_MIN_ENABLE` が原因でマッチするはずのレコードを返さないことがあります。

### 感謝

- shinononさん

- Zhanzhao (Deo) Liangさん

## 12.0.2リリース - 2022-03-29

### 改良

- [logical_range_filter] シャードを処理した直後に参照を減らすようにしました。

  今までGroongaは、 `logical_range_filter` 終了時にすべてのシャードの参照を減らしていました。この機能によって、Groongaは、シャードを処理した後すぐに参照を減らします。この機能によって、 `logical_range_filter` 実行中のメモリー使用量を削減できることがあります。

  この機能は参照カウントモードのときのみ有効です。`GRN_ENABLE_REFERENCE_COUNT=yes` と設定することで、参照カウントモードを有効にできます。

  通常、Groongaは一度でも開いたオブジェクト(テーブル、カラム、インデックスなど)をメモリ上に保持し続けますが、たくさんのオブジェクトを開いた場合、Groongaはたくさんのメモリーを使用します。参照カウントモードでは、どこからも参照されてないオブジェクトをメモリーから開放します。これにより、Groongaのメモリー使用量が減ることがあります。

- クラッシュリカバリー機能の安定性が向上しました。

  この機能は実験的で、デフォルトで無効です。したがって、以下の改良は。一般的なユーザーには影響ありません。

  - Groongaがクラッシュしたときにインデックスが破損する問題を修正しました。

  - ロックが残留する問題を修正しました。

  - クラッシュリカバリー中にGroongaがクラッシュする問題を修正しました。

- 無名マッピングが利用可能な時のmmapのパフォーマンスを向上しました。[GitHub:MariaDB/server#1999][David CARLIERさんの提案]

  この改善によって、Groongaのパフォーマンスが少し向上します。

- [インデックス構築] 以下のタイプのカラムで静的インデックス構築をサポートしました。

  - 非参照重み付きベクターカラム

  - 参照重み付きベクターカラム

  - 参照スカラーカラム

  これらのカラムは、いままで、静的インデックス構築をサポートしていませんでした。そのため、これらのカラムにデータをロードしたあとに、インデックスを構築しても、インデックスの構築時間が長くなっていました。この改良によって、このケースでインデックス構築時間が短くなります。

- [column_create] 新しいフラグ `MISSING_*` と `INVALID_*` を追加しました。

  `column_create` に以下の新しいフラグを追加しました。

  > - `MISSING_ADD`

  > - `MISSING_IGNORE`

  > - `MISSING_NIL`

  > - `INVALID_ERROR`

  > - `INVALID_WARN`

  > - `INVALID_IGNORE`

  通常、データカラムが参照データカラムで存在しないキーを指定された場合、自動的に存在しないキーを作成し、新しいレコードを作ります。

  このGroongaが参照先のカラムにキーを自動的に追加する挙動は、タグ検索のような検索で便利です。Groongaがロード時に自動的にデータを追加してくれるためです。

  しかしながら、この挙動は、キー以外の値が必要な場合に不便です。キーしか存在しないレコードがあるためです。

  このリリースで追加したフラグを使ってこの挙動を変更できます。

  > - `MISSING_ADD`: デフォルト値です。現在と同じ挙動になります。

  >   データカラムが参照データカラムで、存在しないキーを指定された場合、自動的にキーを作成し、新しいレコードを追加します。

  > - `MISSING_IGNORE`:

  >   データカラムが参照データカラムで、存在しないキーを指定された場合、存在しないキーを無視します。参照データカラムがスカラーカラムの場合、値は `GRN_ID_NIL` になります。参照データカラムがベクターカラムの場合、以下のようにその要素のみを無視します。

  >       ["existent1", "nonexistent", "existent2"] ->
  >       ["existent1" "existent2"]

  > - `MISSING_NIL`:

  >   データカラムが参照データカラムで、存在しないキーを指定された場合、スカラーカラムとベクターカラムは存在しないキーを``GRN_ID_NIL`` として扱います。

  >       ["existent1", "nonexistent", "existent2"] ->
  >       ["existent1", "" (GRN_ID_NIL), "existent2"]

  > - `INVALID_ERROR`: デフォルト値です。 ベクターカラムのエラー応答を除いて、現在と同じ挙動になります。

  >   無効な値を設定した場合(e.g.: `XXX` for `UInt8` scalar column)、設定操作をエラーとして扱います。データカラムがスカラーカラムの場合、 `load` は応答とログにエラーを報告します。データカラムがベクターカラムの場合、 `load` はログにエラーを報告しますが、応答にエラーを報告しません。これは非互換の変更です。

  > - `INVALID_WARN`:

  >   無効な値を設定した場合(e.g.: `XXX` for `UInt8` scalar column)、警告メッセージをログに記録し、設定操作を無視します。対象のデータカラムが参照ベクターカラムの場合、`MISSING_IGNORE` と `MISSING_NIL` を使って挙動を決定します。

  > - `INVALID_IGNORE`:

  >   無効な値を設定した場合(e.g.: `XXX` for `UInt8` scalar column)、設定操作を無視します。対象のデータカラムが参照ベクターカラムの場合、`MISSING_IGNORE` と `MISSING_NIL` を使って挙動を決定します。

- [dump][column_list] `MISSING_*` と `INVALID_*` フラグをサポートしました。

  これらのコマンドは、後方互換性を維持するため、 `MISSING_ADD` と `INVALID_ERROR` フラグを表示しません。これらのフラグはデフォルトの挙動を表すためです。

- [schema] `MISSING_*` と `INVALID_*` フラグをサポートしました。

  後方互換性を維持するため、 `MISSING_AND` と `INVALID_ERROR` フラグを `flag` に表示しませんがそれぞれのカラムに、新しく `missing` と `invalid` キーが追加されます。

- Amazon Linux 2向けのパッケージを提供するようにしました。

- [Windows] Visual Studio 2017 でのビルドをやめました。

  GitHub Actionsで windows-2016 のイメージが使えなくなったためです。

### 既知の問題

- 現在Groongaには、ベクターカラムに対してデータを大量に追加、削除、更新した際にデータが破損することがある問題があります。

- `*<` と `*>` は、filter条件の右辺に `query()` を使う時のみ有効です。もし、以下のように指定した場合、 `*<` と `*>` は `&&` として機能します。

  > - `'content @ "Groonga" *< content @ "Mroonga"'`

- `GRN_II_CURSOR_SET_MIN_ENABLE` が原因でマッチするはずのレコードを返さないことがあります。

### 感謝

- David CARLIERさん

## 12.0.1リリース - 2022-02-28

### 改良

- [query_expand] 同義語グループをサポートしました。

  同義語検索をする場合、今までは、以下のようにキーワードとその同義語をそれぞれ定義していました。

      table_create Thesaurus TABLE_PAT_KEY ShortText --normalizer NormalizerAuto
      # [[0, 1337566253.89858, 0.000355720520019531], true]
      column_create Thesaurus synonym COLUMN_VECTOR ShortText
      # [[0, 1337566253.89858, 0.000355720520019531], true]
      load --table Thesaurus
      [
      {"_key": "mroonga", "synonym": ["mroonga", "tritonn", "groonga mysql"]},
      {"_key": "groonga", "synonym": ["groonga", "senna"]}
      ]

  上記のケースでは、`mroonga` を検索した場合、 Groongaは、意図通り、 `mroonga OR tritonn OR "groonga mysql" を検索しますが、``tritonn` を検索した場合は、 Groongaは、 `tritonn` のみを検索します。`tritonn` を検索した場合でも、`tritonn OR mroonga OR "groonga mysql"` と検索した場合、以下のように定義を追加する必要がありました。

      load --table Thesaurus
      [
      {"_key": "tritonn", "synonym": ["tritonn", "mroonga", "groonga mysql"]},
      ]

  多くのケースでは、 `mroonga` を `mroonga OR tritonn OR "groonga mysql"` と展開した場合、 `tritonn` や `"groonga mysql"` も `mroonga OR tritonn OR "groonga mysql"` と展開して欲しくなりますが、今までは、そのようなケースでは定義を追加する必要がありました。したがって、対象のキーワードに同義語がたくさんあると、同じような定義をたくさん定義する必要があるため、同義語の定義が煩雑でした。

  加えて、同義語を削除する際も、多くのレコードを削除する必要があるので面倒でした。

  今回のリリースから同義語の代表値を決めることで一つのグループを作れるようになりました。例えば、以下のすべてのキーワードは、 "mroonga" グループです。

      load --table Synonyms
      [
        {"_key": "mroonga": "representative": "mroonga"}
      ]

      load --table Synonyms
      [
        {"_key": "tritonn": "representative": "mroonga"},
        {"_key": "groonga mysql": "representative": "mroonga"}
      ]

  このケースでは、 `mroonga` は `mroonga OR tritonn OR "groonga mysql"` と展開されます。また、 `tritonn` や `"groonga mysql"` も `mroonga OR tritonn OR "groonga mysql"` と展開されます。

  同義語を削除する際も、対象のレコードを削除するだけです。例えば、同義語から `"groonga mysql"` を削除する場合は、 `{"_key": "groonga mysql": "representative": "mroonga"}` を削除するだけです。

- [query_expand] 同義語グループにベクターを使えるようにしました。

  以下のように、同義語グループにベクターを使えます。

      table_create SynonymGroups TABLE_NO_KEY
      [[0,0.0,0.0],true]
      column_create SynonymGroups synonyms COLUMN_VECTOR ShortText
      [[0,0.0,0.0],true]
      table_create Synonyms TABLE_PAT_KEY ShortText
      [[0,0.0,0.0],true]
      column_create Synonyms group COLUMN_INDEX SynonymGroups synonyms
      [[0,0.0,0.0],true]
      load --table SynonymGroups
      [
      ["synonyms"],
      [["rroonga", "Ruby groonga"]],
      [["groonga", "rroonga", "mroonga"]]
      ]
      [[0,0.0,0.0],2]
      query_expand Synonyms.group "rroonga"
      [
        [
          0,
          0.0,
          0.0
        ],
        "((rroonga) OR (Ruby groonga) OR (groonga) OR (rroonga) OR (mroonga))"
      ]

- 環境変数によって、バックトレースを無効にできるようにしました。

  `GRN_BACK_TRACE_ENABLE` を使うことで、バックトレースの出力を無効にできます。`GRN_BACK_TRACE_ENABLE=no` と設定すると、Groongaはバックトレースを出力しません。

  Groongaはバックトレースをスタック領域に保持します。したがって、OSによっては、Groongaがスタック領域を使い切ってしまいクラッシュする可能性があります。`GRN_BACK_TRACE_ENABLE=no` を使うことで、このようなケースを避けることができます。

- [select] `--slices` のパフォーマンスを改善しました。

- [Windows] VisualStudio 2022 をサポートしました。

- [select] 近傍検索でそれぞれの要素ごとの距離を指定できるようになりました。

  例えば、近傍フレーズ検索なら、フレーズごとに最大距離を指定できます。この機能は今後ドキュメント化されます。そのため、機能の詳細は後日、共有します。

- [Groonga HTTPサーバー] RPMパッケージのGroongaであっても、 `groonga-server-http` を使えるようにしました。

### 修正

- [Windows] Groongaがバックトレースを出力時にクラッシュする問題を修正しました。

### 既知の問題

- 現在Groongaには、ベクターカラムに対してデータを大量に追加、削除、更新した際にデータが破損することがある問題があります。

- `*<` と `*>` は、filter条件の右辺に `query()` を使う時のみ有効です。もし、以下のように指定した場合、 `*<` と `*>` は `&&` として機能します。

  > - `'content @ "Groonga" *< content @ "Mroonga"'`

- `GRN_II_CURSOR_SET_MIN_ENABLE` が原因でマッチするはずのレコードを返さないことがあります。

## 12.0.0リリース - 2022-02-09

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

まずはじめに Groonga 11.0.0 から 11.1.3 までの変更点を紹介します。次に、12.0.0の主な変更点を紹介します。

### Groonga 11.0.0 から 11.1.3 までの主な変更点

#### 新規機能と改良

- [snippet] 32個以上のキーワードを使えるようにしました。

  いままで、 `snippet` は32個以上のキーワードを指定できませんでしたが、この改良によって、32個以上のキーワードを指定できます。

  通常の使用では、 `snippet` に32以上のキーワードは指定しませんが、 `query_expand` などを使うことによって自動的にキーワードが増加したときに対象のキーワードが32以上になることがあります。

  今までは、このようなケースでは、Groongaはエラーになっていましたが、この改良によって、エラーが発生しなくなります。

  詳細は、 release 11.1.3 を参照してください。

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

  このオプションは、正規化対象の文字列から記号(例えば #, !, ", &, % 等)を削除します。例えば、歌のタイトルやアーティスト名、お店の名前等の表記ゆれの防止に使えます。

  詳細は、 release 11.1.3 を参照してください。

- [load] ISO 8601 形式をサポートしました。

  ISO 8601形式は一般的なフォーマットです。より一般的な形式をサポートしたことによって `load` の使い勝手が良くなりました。

  詳細は、 release 11.1.0 を参照してください。

- [snippet] 正規表現を使ってスニペットの区切り文字を見つける新しいオプション `delimiter_regexp` を追加しました。

  この機能は検索結果を文で表示したい時に便利です。

  snippet は、検索キーワードの周辺のテキストを抽出します。 snippet で抽出したテキストをスニペットと呼びます。

  通常、 snippet は、検索キーワードの周辺の200byteのテキストを返しますが、 snippet は、センテンスの区切りを考慮しません。スニペットは、複数のセンテンスで構成されることがあります。

  `delimiter_regexp` オプションは、検索キーワードと同じセンテンスのテキストのみを抽出したいときに便利です。例えば、 `\.\s*` を使って対象のセンテンス内のテキストのみを抽出できます。文字列は、 `\` でエスケープする必要があることに注意してください。

  詳細は、 release 11.0.9 を参照してください。

- [cache_limit] `cache_limit 0` を実行したときにクエリーキャッシュを削除するようにしました。

  Groongaは内部的なテーブルにクエリーキャッシュを保存しています。このテーブルは、ハッシュテーブルなので、トータルのキーサイズは最大で4GiBです。そのため、もし多くの巨大なクエリーを実行した場合、トータルのキーサイズの最大値4GiBを超え、Groongaがクエリーをキャッシュできない可能性があります。このようなケースで、 `cache_limit 0` を実行することで、クエリーキャッシュ用のテーブルをクリアーし、Groongaがクエリーキャッシュを保存できるようにします。

  今まではこの問題を解消するには、Groongaを再起動する必要がありましたが、この改良によって、 `cache_limit 0` を実行するだけで問題を解消できます。

  詳細は、 release 11.0.6 を参照してください。

- [between] `between()` で、条件式の評価順序の最適化をサポートしました。

  `GRN_EXPR_OPTIMIZE=yes` を設定することで、 `between()` で条件式の評価順序の最適化を使えます。この最適化は、 `between()` で十分にレコードを絞り込めるか、 `between()` でほとんどレコードを絞り込めない時に効果があります。

- [ログ] 標準出力、標準エラー出力への出力をサポートしました。

  この機能はDocker上でGroongaを実行する際に有用です。Dockerは標準で標準出力と標準エラー出力を記録する機能を持っています。したがって、Groongaのログを取得するために、Dockerの環境にログインする必要がなくなります。

  詳細は、 release 11.0.4 を参照してください。

- [query] クエリー毎に `TokenFilterStem` と `TokenFilterStopWord` を無効にできるようになりました。

  特定のクエリーでのみ `TokenFilterStem` と `TokenFilterStopWord` を無効にして検索できるようになりました。

  この機能は、検索キーワードと正確に同じ語を検索したい時に便利です。通常、ステミングやストップワードの除去を有効にしたほうが良い結果を得られますが、検索キーワードと正確に同じ語を検索したい場合は、これらの機能は不要です。

  今までは、検索キーワードと正確に同じ語を検索したい場合は、専用のインデックスを作る必要がありましたが、この改良によって、専用のインデックスを作らずに検索キーワードと正確に同じ語を検索できます。

  詳細は、 release 11.0.3 を参照してください。

- [string_slice] 新しい関数 `string_slice` を追加しました。

  `string_slice()` は、検索結果の文字列から文字の位置や正規表現を使って、部分文字列を抽出します。この機能は、検索結果を編集したい時に便利です。

  例えば、この機能は、検索結果からタグを除去するのに使えます。

- [query_parallel_or] クエリーを並行して実行できる新しい関数を追加しました。

  `query_parallel_or` は query と似ていますが、 `query_parallel_or` は複数の OR 条件を並列に処理します。この機能を使うことで、大量のOR条件の実行速度を向上できます。

  ただ、 `query_parallel_or` だけで複数のCPUを使います。したがって、 `query_parallel_or` と同時に実行しているクエリーは速度が低下する可能性があります。

- [トークンフィルター] オプションをつけた複数のトークンフィルターを使えるようにしました。

  以下の例のように、オプション付きのトークンフィルターを複数使うことができます。

      --token_filters 'TokenFilterStopWord("column", "ignore"), TokenFilterNFKC130("unify_kana", true)'

- [select] `--post_filter` と `--slices[].post_filter` をサポートしました。

  `--post_filter` と `--slices[].post_filter` を使うことで、 `--filter` 実行後に再度フィルタリングすることができます。`--post_filter` と `--slices[].post_filter` の違いは応答フォーマットです。

  `--post_filter` の応答フォーマットは、 `--filter` と同じです。`--slices[].post_filter` の応答フォーマットは `--slices[].post_filter` の実行前後の結果を出力します。

  `--slices[].post_filter` の応答フォーマットは、通常の `select` の応答と異なることに注意してください。

#### 修正

- Groongaが依存している arrow-libs がバージョンアップしたことによって、Groongaのバージョンアップが失敗する問題を修正しました。

  ただし、 arrow-libs がメジャーバージョンアップした場合は、この問題は再発します。その場合は、Groongaパッケージを再構築して対応する予定です。

  This bug only occurs AlmaLinux 8 and CentOS 7.

- [Windows] メモリー不足によって、新しくファイルのオープンに失敗した時にリソースリークする問題を修正しました。

- オプションをサポートしているトークナイザーやノーマライザー、トークンフィルターが使われている際、多くの検索クエリーを送信するとGroongaが応答を返さなくなることがある問題を修正しました。

- インデックス内のデータを大量に追加、削除、更新した際にインデックスが破損することがある問題を修正しました。

  この問題は、インデックス内のデータを大量に削除しただけでも発生します。ただ、インデックスにデータを追加しただけでは発生しません。

  詳細は、 release 11.0.0 を参照してください。

#### 新しくサポートしたOS

- [AlmaLinux] AlmaLinux 8 向けのパッケージをサポートしました。

- [AlmaLinux] ARM64版 AlmaLinux 8 向けのパッケージをサポートしました。

- [Debian GNU/Linux] Debian 11 (Bullseye) をサポートしました。

- [Debian GNU/Linux] ARM64版 Debian 11 (Bullseye) と ARM64版 Debian 10 (buster) をサポートしました。

- [Ubuntu] Ubuntu 21.10 (Impish Indri)をサポートしました。

#### サポートをやめたOS

- [CentOS] CentOS 8のサポートをやめました。

- [Ubuntu] Ubuntu 21.04 (Hirsute Hippo)のサポートをやめました。

- [Ubuntu] Ubuntu 20.10 (Groovy Gorilla)のサポートをやめました。

- [Ubuntu] Ubuntu 16.04 LTS (Xenial Xerus)のサポートをやめました。

- [Windows] Linux上のMinGWを使ってクロスコンパイルしていた以下のWindows向けパッケージの提供をやめました。

  - groonga-x.x.x-x86.exe

  - groonga-x.x.x-x86.zip

  - groonga-x.x.x-x64.exe

  - groonga-x.x.x-x86.zip

#### 感謝

- naoaさん

- Anthony M. Cookさん

- MASUDA Kazuhiroさん

- potiさん

- Takashi Hashidaさん

- higchiさん

- wi24rdさん

- Josep Sanzさん

- Keitaro YOSHIMURAさん

- shibanao4870さん

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

### 改良

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

  このオプションで、 `GRN_SUB_FILTER_PRE_FILTER_THRESHOLD` の値を変更できます。Groongaが `sub_filter` 実行時に レコード数が `GRN_SUB_FILTER_PRE_FILTER_THRESHOLD` 以下だった場合、Groongaは既に絞り込んだレコードに対して `sub_filter` を実行します。

  -1にすると、常にこの最適化を有効にできます。

- [index_column_have_source_record] 新しい関数 `index_column_have_source_record()` を追加しました。

  インデックスに存在するトークンがGroongaに登録されているいずれかのレコードに含まれているかどうかを確認できます。

  Groongaは、レコードの更新によってどのレコードからも使われていないトークンがあっても、それを削除しません。したがって、例えば、オートコンプリート機能を使っていると、検索候補としてどのレコードにも含まれていないトークンを返す可能性がありますが、この関数をつかうことで、不要なトークンを返さないようにできます。

  この関数は、トークンがどのレコードにも含まれていないことを検出できるからです。

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

  このオプションは、先頭と末尾から空白を削除します。

      normalize \
      'NormalizerNFKC121("strip", true, \
                         "report_source_offset", true)' \
      "  hello world\t! \t " \
      WITH_CHECKS|WITH_TYPES
       [
         [
           0,
           0.0,
           0.0
         ],
         {
           "normalized": "hello world!",
           "types": [
             "alpha",
             "alpha",
             "alpha",
             "alpha",
             "alpha",
             "others",
             "alpha",
             "alpha",
             "alpha",
             "alpha",
             "alpha|blank",
             "symbol|blank"
           ],
           "checks": [
             3,
             1,
             1,
             1,
             1,
             1,
             1,
             1,
             1,
             1,
             1,
             2
           ],
           "offsets": [
             0,
             3,
             4,
             5,
             6,
             7,
             8,
             9,
             10,
             11,
             12,
             14
           ]
         }
       ]

- [select] 新しい引数 `drilldown_max_n_target_records` と `drilldown[${LABEL}].max_n_target_records` を追加しました。

  ドリルダウン対象のテーブル（フィルター結果）の中のうち最大で何レコードをドリルダウンに使うかを指定します。もし、フィルター結果のレコード数が指定した値より大きかったらフィルターした結果内のいくつかのレコードはドリルダウンには使われません。これらの引数のデフォルト値は、 `-1` です。これらの引数に `-1` がセットされた場合、Groongaは全てのレコードをドリルダウンに使います。

  この機能はフィルター結果が非常に大きくなるかもしれない場合に有用です。大きなフィルター結果に対するドリルダウンは遅くなることがあるためです。この機能を使うことでドリルダウンに使うレコード数を制限できます。

  以下はドリルダウンに使う最大レコード数を制限する例です。最後の2レコード（ `{"_id": 4, "tag": "Senna"}` と `{"_id": 5, "tag": "Senna"}` ）は使われていません。

      table_create Entries TABLE_HASH_KEY ShortText
      column_create Entries content COLUMN_SCALAR Text
      column_create Entries n_likes COLUMN_SCALAR UInt32
      column_create Entries tag COLUMN_SCALAR ShortText

      table_create Terms TABLE_PAT_KEY ShortText --default_tokenizer TokenBigram --normalizer NormalizerAuto
      column_create Terms entries_key_index COLUMN_INDEX|WITH_POSITION Entries _key
      column_create Terms entries_content_index COLUMN_INDEX|WITH_POSITION Entries content
      load --table Entries
      [
      {"_key":    "The first post!",
       "content": "Welcome! This is my first post!",
       "n_likes": 5,
       "tag": "Hello"},
      {"_key":    "Groonga",
       "content": "I started to use Groonga. It's very fast!",
       "n_likes": 10,
       "tag": "Groonga"},
      {"_key":    "Mroonga",
       "content": "I also started to use Mroonga. It's also very fast! Really fast!",
       "n_likes": 15,
       "tag": "Groonga"},
      {"_key":    "Good-bye Senna",
       "content": "I migrated all Senna system!",
       "n_likes": 3,
       "tag": "Senna"},
      {"_key":    "Good-bye Tritonn",
       "content": "I also migrated all Tritonn system!",
       "n_likes": 3,
       "tag": "Senna"}
      ]

      select Entries \
        --limit -1 \
        --output_columns _id,tag \
        --drilldown tag \
        --drilldown_max_n_target_records 3
      [
        [
          0,
          1337566253.89858,
          0.000355720520019531
        ],
        [
          [
            [
              5
            ],
            [
              [
                "_id",
                "UInt32"
              ],
              [
                "tag",
                "ShortText"
              ]
            ],
            [
              1,
              "Hello"
            ],
            [
              2,
              "Groonga"
            ],
            [
              3,
              "Groonga"
            ],
            [
              4,
              "Senna"
            ],
            [
              5,
              "Senna"
            ]
          ],
          [
            [
              2
            ],
            [
              [
                "_key",
                "ShortText"
              ],
              [
                "_nsubrecs",
                "Int32"
              ]
            ],
            [
              "Hello",
              1
            ],
            [
              "Groonga",
              2
            ]
          ]
        ]
      ]

- [httpd] バンドルしているnginxのバージョンを1.21.6に更新しました。

## 11.1.3リリース - 2022-01-29

### 改良

- [snippet] 32個以上のキーワードを使えるようにしました。 [GitHub#1313][Takashi Hashidaさんがパッチ提供]

  いままで、 `snippet` は32個以上のキーワードを指定できませんでしたが、この改良によって、以下のように32個以上のキーワードを指定できます。

      table_create Entries TABLE_NO_KEY
      column_create Entries content COLUMN_SCALAR ShortText

      load --table Entries
      [
      {"content": "Groonga is a fast and accurate full text search engine based on inverted index. One of the characteristics of Groonga is that a newly registered document instantly appears in search results. Also, Groonga allows updates without read locks. These characteristics result in superior performance on real-time applications.\nGroonga is also a column-oriented database management system (DBMS). Compared with well-known row-oriented systems, such as MySQL and PostgreSQL, column-oriented systems are more suited for aggregate queries. Due to this advantage, Groonga can cover weakness of row-oriented systems.\nThe basic functions of Groonga are provided in a C library. Also, libraries for using Groonga in other languages, such as Ruby, are provided by related projects. In addition, groonga-based storage engines are provided for MySQL and PostgreSQL. These libraries and storage engines allow any application to use Groonga. See usage examples."},
      {"content": "In widely used DBMSs, updates are immediately processed, for example, a newly registered record appears in the result of the next query. In contrast, some full text search engines do not support instant updates, because it is difficult to dynamically update inverted indexes, the underlying data structure.\nGroonga also uses inverted indexes but supports instant updates. In addition, Groonga allows you to search documents even when updating the document collection. Due to these superior characteristics, Groonga is very flexible as a full text search engine. Also, Groonga always shows good performance because it divides a large task, inverted index merging, into smaller tasks."}
      ]

      select Entries \
        --output_columns ' \
        snippet(content, \
        "groonga", "inverted", "index", "fast", "full", "text", "search", "engine", "registered", "document", \
        "results", "appears", "also", "system", "libraries", "for", "mysql", "postgresql", "column-oriented", "dbms", \
        "basic", "ruby", "projects", "storage", "allow", "application", "usage", "sql", "well-known", "real-time", \
        "weakness", "merging", "performance", "superior", "large", "dynamically", "difficult", "query", "examples", "divides", \
        { \
          "default_open_tag": "[", \
          "default_close_tag": "]", \
          "width" : 2048 \
        })'
      [
        [
          0,
          1643165838.691991,
          0.0003311634063720703
        ],
        [
          [
            [
              2
            ],
            [
              [
                "snippet",
                null
              ]
            ],
            [
              [
                "[Groonga] is a [fast] and accurate [full] [text] [search] [engine] based on [inverted] [index]. One of the characteristics of [Groonga] is that a newly [registered] [document] instantly [appears] in [search] [results]. [Also], [Groonga] [allow]s updates without read locks. These characteristics result in [superior] [performance] on [real-time] [application]s.\n[Groonga] is [also] a [column-oriented] database management [system] ([DBMS]). Compared with [well-known] row-oriented [system]s, such as [MySQL] and [PostgreSQL], [column-oriented] [system]s are more suited [for] aggregate queries. Due to this advantage, [Groonga] can cover [weakness] of row-oriented [system]s.\nThe [basic] functions of [Groonga] are provided in a C library. [Also], [libraries] [for] using [Groonga] in other languages, such as [Ruby], are provided by related [projects]. In addition, [groonga]-based [storage] [engine]s are provided [for] [MySQL] and [PostgreSQL]. These [libraries] and [storage] [engine]s [allow] any [application] to use [Groonga]. See [usage] [examples]."
              ]
            ],
            [
              [
                "In widely used [DBMS]s, updates are immediately processed, [for] example, a newly [registered] record [appears] in the result of the next [query]. In contrast, some [full] [text] [search] [engine]s do not support instant updates, because it is [difficult] to [dynamically] update [inverted] [index]es, the underlying data structure.\n[Groonga] [also] uses [inverted] [index]es but supports instant updates. In addition, [Groonga] [allow]s you to [search] [document]s even when updating the [document] collection. Due to these [superior] characteristics, [Groonga] is very flexible as a [full] [text] [search] [engine]. [Also], [Groonga] always shows good [performance] because it [divides] a [large] task, [inverted] [index] [merging], into smaller tasks."
              ]
            ]
          ]
        ]
      ]

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

  このオプションは、以下のように正規化対象の文字列から記号(例えば #, !, ", &, % 等)を削除します。

      normalize   'NormalizerNFKC130("remove_symbol", true)'   "#This & is %% a pen."   WITH_TYPES
      [
        [
          0,
          1643595008.729597,
          0.0005540847778320312
        ],
        {
          "normalized": "this  is  a pen",
          "types": [
            "alpha",
            "alpha",
            "alpha",
            "alpha",
            "others",
            "others",
            "alpha",
            "alpha",
            "others",
            "others",
            "alpha",
            "others",
            "alpha",
            "alpha",
            "alpha"
          ],
          "checks": [
          ]
        }
      ]

- [AlmaLinux] ARM64版 AlmaLinux 8 向けのパッケージをサポートしました。

- [httpd] バンドルしているnginxのバージョンを1.21.5に更新しました。

- [Documentation] ruby_eval の誤記を修正しました。[GitHub#1317][wi24rdさんがパッチ提供]

- [Ubuntu] Ubuntu 21.04 (Hirsute Hippo)サポートをやめました。

  - Ubuntu 21.04 は、2022年1月20日でEOLとなったためです。

### 修正

- [load] 存在しないカラムを指定してロードした時にクラッシュする問題を修正しました。

  この問題は、 `load` の引数として、 `input_type` に `apache-arrow` を指定したときのみ発生します。

- Groongaが依存している arrow-libs がバージョンアップしたことによって、Groongaのバージョンアップが失敗する問題を修正しました。[groonga-talk,540][Josep Sanzさんの報告][Gitter,61eaaa306d9ba23328d23ce1][shibanao4870さんの報告][GitHub#1316][Keitaro YOSHIMURAさんの報告]

  ただし、 arrow-libs がメジャーバージョンアップした場合は、この問題は再発します。その場合は、Groongaパッケージを再構築して対応する予定です。

### 既知の問題

- 現在Groongaには、ベクターカラムに対してデータを大量に追加、削除、更新した際にデータが破損することがある問題があります。

- `*<` と `*>` は、filter条件の右辺に `query()` を使う時のみ有効です。もし、以下のように指定した場合、 `*<` と `*>` は `&&` として機能します。

  > - `'content @ "Groonga" *< content @ "Mroonga"'`

- `GRN_II_CURSOR_SET_MIN_ENABLE` が原因でマッチするはずのレコードを返さないことがあります。

### 感謝

- Takashi Hashidaさん

- wi24rdさん

- Josep Sanzさん

- Keitaro YOSHIMURAさん

- shibanao4870さん

## 11.1.1リリース - 2021-12-29

### 改良

- [select] 組み合わせフレーズ近傍検索をサポートしました。

  この機能は、 `'*NP"..." OR *NP"..." OR ...'` の短縮形です。例えば、以下のように、 `query` を使って `*NP` を複数実行する式のかわりに `*NPP` を使えます。

      query ("title * 10 || content",
             "*NP"a 1 x" OR
              *NP"a 1 y" OR
              *NP"a 1 z" OR
              *NP"a 2 x" OR
              *NP"a 2 y" OR
              *NP"a 2 z" OR
              *NP"a 3 x" OR
              *NP"a 3 y" OR
              *NP"a 3 z" OR
              *NP"b 1 x" OR
              *NP"b 1 y" OR
              *NP"b 1 z" OR
              *NP"b 2 x" OR
              *NP"b 2 y" OR
              *NP"b 2 z" OR
              *NP"b 3 x" OR
              *NP"b 3 y" OR
              *NP"b 3 z"")

  この機能によって、上記の式を `*NPP"(a b) (1 2 3) (x y z)"` と書くことができます。加えて、 `*NPP"(a b) (1 2 3) (x y z)"` は、 `'*NP"..." OR *NP"..." OR ...'` より高速です。

      query ("title * 10 || content",
             "*NPP"(a b) (1 2 3) (x y z)"")

  この機能は、 `'*NP"..." OR *NP"..." OR ...'` のような近傍フレーズ検索のパフォーマンスを改善するために実装されました。

- [select] 順序付き組み合わせフレーズ近傍検索をサポートしました。

  この機能は、 `'*ONP"..." OR *ONP"..." OR ...'` の短縮形です。例えば、以下のように、 `query` を使って `*ONP` を複数実行する式のかわりに `*ONPP` を使えます。

      query ("title * 10 || content",
             "*ONP"a 1 x" OR
              *ONP"a 1 y" OR
              *ONP"a 1 z" OR
              *ONP"a 2 x" OR
              *ONP"a 2 y" OR
              *ONP"a 2 z" OR
              *ONP"a 3 x" OR
              *ONP"a 3 y" OR
              *ONP"a 3 z" OR
              *ONP"b 1 x" OR
              *ONP"b 1 y" OR
              *ONP"b 1 z" OR
              *ONP"b 2 x" OR
              *ONP"b 2 y" OR
              *ONP"b 2 z" OR
              *ONP"b 3 x" OR
              *ONP"b 3 y" OR
              *ONP"b 3 z"")

  この機能によって、上記の式を `*ONPP"(a b) (1 2 3) (x y z)"` と書くことができます。加えて、 `*ONPP"(a b) (1 2 3) (x y z)"` は、 `'*ONP"..." OR *ONP"..." OR ...'` より高速です。

      query ("title * 10 || content",
             "*ONPP"(a b) (1 2 3) (x y z)"")

  この機能は `'*ONP"..." OR *ONP"..." OR ...'` のような順序付き近傍フレーズ検索のパフォーマンスを改善するために実装されました。

- [request_cancel] 検索実行中に `request_cancel` を検知しやすくしました。

  `request_cancel` を検知するために、リターンコードのチェックを増やしたためです。

- [thread_dump] 新しいコマンド `thread_dump` を追加しました。

  現状、このコマンドはWindowsでしか動作しません。

  このコマンド実行時の全てのスレッドのバックトレースをNOTICEレベルのログとして出力できます。

  この機能は、Groongaが応答を返さない等の問題を解決するのに役立ちます。

- [CentOS] CentOS 8のサポートをやめました。

  CentOS 8は、2021年12月31日でEOLとなるためです。

### 修正

- 無効なパラメータを持つインデックスカラムを削除できない問題を修正しました。 [GitHub#1301][Takashi Hashidaさんがパッチ提供]

  - 例えば、以下のように `column_create` を使って無効なインデックスカラムを作成した時、テーブルが削除できなくなります。

        table_create Statuses TABLE_NO_KEY
        column_create Statuses start_time COLUMN_SCALAR UInt16
        column_create Statuses end_time COLUMN_SCALAR UInt16

        table_create Times TABLE_PAT_KEY UInt16
        column_create Times statuses COLUMN_INDEX Statuses start_time,end_time
        [
          [
            -22,
            1639037503.16114,
            0.003981828689575195,
            "grn_obj_set_info(): GRN_INFO_SOURCE: multi column index must be created with WITH_SECTION flag: <Times.statuses>",
            [
              [
                "grn_obj_set_info_source_validate",
                "../../groonga/lib/db.c",
                9605
              ],
              [
                "/tmp/d.grn",
                6,
                "column_create Times statuses COLUMN_INDEX Statuses start_time,end_time"
              ]
            ]
          ],
          false
        ]
        table_remove Times
        [
          [
            -22,
            1639037503.16515,
            0.0005414485931396484,
            "[object][remove] column is broken: <Times.statuses>",
            [
              [
                "remove_columns",
                "../../groonga/lib/db.c",
                10649
              ],
              [
                "/tmp/d.grn",
                8,
                "table_remove Times"
              ]
            ]
          ],
          false
        ]

### 既知の問題

- 現在Groongaには、ベクターカラムに対してデータを大量に追加、削除、更新した際にデータが破損することがある問題があります。

- `*<` と `*>` は、filter条件の右辺に `query()` を使う時のみ有効です。もし、以下のように指定した場合、 `*<` と `*>` は `&&` として機能します。

  > - `'content @ "Groonga" *< content @ "Mroonga"'`

- `GRN_II_CURSOR_SET_MIN_ENABLE` が原因でマッチするはずのレコードを返さないことがあります。

### 感謝

- Takashi Hashidaさん

## 11.1.0リリース - 2021-11-29

### 改良

- [load] ISO 8601 形式をサポートしました。[GitHub#1228][Takashi Hashidaさんがパッチ提供]

  この変更によって、`load` は、以下のフォーマットをサポートします。

  > - YYYY-MM-ddThh:mm:ss.sZ

  > - YYYY-MM-ddThh:mm:ss.s+10:00

  > - YYYY-MM-ddThh:mm:ss.s-10:00

  この構文の `T` と `Z` の代わりに `t` と `z` を使うこともできます。`-` の代わりに `/` を使うこともできます。ただし、 `/` は、ISO 8601 形式ではないことに注意してください。`/` は互換性のためにサポートしています。

      plugin_register functions/time

      table_create Logs TABLE_NO_KEY
      column_create Logs case COLUMN_SCALAR ShortText
      column_create Logs created_at COLUMN_SCALAR Time
      column_create Logs created_at_text COLUMN_SCALAR ShortText

      load --table Logs
      [
      {"case": "timezone: Z", "created_at": "2000-01-01T10:00:00Z", "created_at_text": "2000-01-01T10:00:00Z"},
      {"case": "timezone: z", "created_at": "2000-01-01t10:00:00z", "created_at_text": "2000-01-01T10:00:00z"},
      {"case": "timezone: 00:00", "created_at": "2000-01-01T10:00:00+00:00", "created_at_text": "2000-01-01T10:00:00+00:00"},
      {"case": "timezone: +01:01", "created_at": "2000-01-01T11:01:00+01:01", "created_at_text": "2000-01-01T11:01:00+01:01"},
      {"case": "timezone: +11:11", "created_at": "2000-01-01T21:11:00+11:11", "created_at_text": "2000-01-01T21:11:00+11:11"},
      {"case": "timezone: -01:01", "created_at": "2000-01-01T08:59:00-01:01", "created_at_text": "2000-01-01T08:59:00-01:01"},
      {"case": "timezone: -11:11", "created_at": "1999-12-31T22:49:00-11:11", "created_at_text": "1999-12-31T22:49:00-11:11"},
      {"case": "timezone hour threshold: +23:00", "created_at": "2000-01-02T09:00:00+23:00", "created_at_text": "2000-01-02T09:00:00+23:00"},
      {"case": "timezone minute threshold: +00:59", "created_at": "2000-01-01T10:59:00+00:59", "created_at_text": "2000-01-01T10:59:00+00:59"},
      {"case": "timezone omitting minute: +01", "created_at": "2000-01-01T11:00:00+01", "created_at_text": "2000-01-01T11:00:00+01"},
      {"case": "timezone omitting minute: -01", "created_at": "2000-01-01T09:00:00-01", "created_at_text": "2000-01-01T09:00:00-01"},
      {"case": "timezone: localtime", "created_at": "2000-01-01T19:00:00", "created_at_text": "2000-01-01T19:00:00"},
      {"case": "compatible: date delimiter: /", "created_at": "2000/01/01T10:00:00Z", "created_at_text": "2000/01/01T10:00:00Z"},
      {"case": "decimal", "created_at": "2000-01-01T11:01:00.123+01:01", "created_at_text": "2000-01-01T11:01:00.123+01:01"}
      ]

      select Logs \
        --limit -1 \
        --output_columns "case, time_format_iso8601(created_at), created_at_text"
      [
        [
          0,
          0.0,
          0.0
        ],
        [
          [
            [
              14
            ],
            [
              [
                "case",
                "ShortText"
              ],
              [
                "time_format_iso8601",
                null
              ],
              [
                "created_at_text",
                "ShortText"
              ]
            ],
            [
              "timezone: Z",
              "2000-01-01T19:00:00.000000+09:00",
              "2000-01-01T10:00:00Z"
            ],
            [
              "timezone: z",
              "2000-01-01T19:00:00.000000+09:00",
              "2000-01-01T10:00:00z"
            ],
            [
              "timezone: 00:00",
              "2000-01-01T19:00:00.000000+09:00",
              "2000-01-01T10:00:00+00:00"
            ],
            [
              "timezone: +01:01",
              "2000-01-01T19:00:00.000000+09:00",
              "2000-01-01T11:01:00+01:01"
            ],
            [
              "timezone: +11:11",
              "2000-01-01T19:00:00.000000+09:00",
              "2000-01-01T21:11:00+11:11"
            ],
            [
              "timezone: -01:01",
              "2000-01-01T19:00:00.000000+09:00",
              "2000-01-01T08:59:00-01:01"
            ],
            [
              "timezone: -11:11",
              "2000-01-01T19:00:00.000000+09:00",
              "1999-12-31T22:49:00-11:11"
            ],
            [
              "timezone hour threshold: +23:00",
              "2000-01-01T19:00:00.000000+09:00",
              "2000-01-02T09:00:00+23:00"
            ],
            [
              "timezone minute threshold: +00:59",
              "2000-01-01T19:00:00.000000+09:00",
              "2000-01-01T10:59:00+00:59"
            ],
            [
              "timezone omitting minute: +01",
              "2000-01-01T19:00:00.000000+09:00",
              "2000-01-01T11:00:00+01"
            ],
            [
              "timezone omitting minute: -01",
              "2000-01-01T19:00:00.000000+09:00",
              "2000-01-01T09:00:00-01"
            ],
            [
              "timezone: localtime",
              "2000-01-01T19:00:00.000000+09:00",
              "2000-01-01T19:00:00"
            ],
            [
              "compatible: date delimiter: /",
              "2000-01-01T19:00:00.000000+09:00",
              "2000/01/01T10:00:00Z"
            ],
            [
              "decimal",
              "2000-01-01T19:00:00.123000+09:00",
              "2000-01-01T11:01:00.123+01:01"
            ]
          ]
        ]
      ]

- [select] 新しい `query_flags` `DISABLE_PREFIX_SEARCH` を追加しました。

  以下のように、`DISABLE_PREFIX_SEARCH` によって、前方一致検索の演算子の `^` と `*` を検索キーワードとして使えます。

  この機能は、 `^` や `*` を含むドキュメントを検索したい時に便利です。

      table_create Users TABLE_PAT_KEY ShortText

      load --table Users
      [
      {"_key": "alice"},
      {"_key": "alan"},
      {"_key": "ba*"}
      ]

      select Users \
        --match_columns "_key" \
        --query "a*" \
        --query_flags "DISABLE_PREFIX_SEARCH"
      [[0,0.0,0.0],[[[1],[["_id","UInt32"],["_key","ShortText"]],[3,"ba*"]]]]

      table_create Users TABLE_PAT_KEY ShortText

      load --table Users
      [
      {"_key": "alice"},
      {"_key": "alan"},
      {"_key": "^a"}
      ]

      select Users \
        --query "_key:^a" \
        --query_flags "ALLOW_COLUMN|DISABLE_PREFIX_SEARCH"
      [[0,0.0,0.0],[[[1],[["_id","UInt32"],["_key","ShortText"]],[3,"^a"]]]]

- [select] 新しい `query_flags` `DISABLE_AND_NOT` を追加しました。

  以下のように、 `DISABLE_AND_NOT` によって、 `AND NOT` の演算子の `-` を検索キーワードとして使えます。

  この機能は、 `-` を含むドキュメントを検索したい時に便利です。

      table_create Users TABLE_PAT_KEY ShortText

      load --table Users
      [
      {"_key": "alice"},
      {"_key": "bob"},
      {"_key": "cab-"}
      ]

      select Users   --match_columns "_key"   --query "b - a"   --query_flags "DISABLE_AND_NOT"
      [[0,0.0,0.0],[[[1],[["_id","UInt32"],["_key","ShortText"]],[3,"cab-"]]]]

### 修正

- [ブラウザーベースの管理ツール] レコード一覧の管理モードのチェックボックスにチェックを入れても、非管理モードに入力された検索クエリーが送信される問題を修正しました。 [Github#1186][Takashi Hashidaさんがパッチ提供]

### 既知の問題

- 現在Groongaには、ベクターカラムに対してデータを大量に追加、削除、更新した際にデータが破損することがある問題があります。

- `*<` と `*>` は、filter条件の右辺に `query()` を使う時のみ有効です。もし、以下のように指定した場合、 `*<` と `*>` は `&&` として機能します。

  > - `'content @ "Groonga" *< content @ "Mroonga"'`

- `GRN_II_CURSOR_SET_MIN_ENABLE` が原因でマッチするはずのレコードを返さないことがあります。

### 感謝

- Takashi Hashidaさん

## 11.0.9リリース - 2021-11-04

### 改良

- [snippet] 正規表現を使ってスニペットの区切り文字を見つける新しいオプション `delimiter_regexp` を追加しました。

  snippet は、検索キーワードの周辺のテキストを抽出します。 snippet で抽出したテキストをスニペットと呼びます。

  通常、 snippet は、検索キーワードの周辺の200byteのテキストを返しますが、 snippet は、センテンスの区切りを考慮しません。スニペットは、複数のセンテンスで構成されることがあります。

  `delimiter_regexp` オプションは、検索キーワードと同じセンテンスのテキストのみを抽出したいときに便利です。例えば、以下のように、 `\.\s*` を使って対象のセンテンス内のテキストのみを抽出できます。文字列は、 `\` でエスケープする必要があることに注意してください。

  >     table_create Documents TABLE_NO_KEY
  >     column_create Documents content COLUMN_SCALAR Text

  >     table_create Terms TABLE_PAT_KEY ShortText --default_tokenizer TokenBigram  --normalizer NormalizerAuto
  >     column_create Terms documents_content_index COLUMN_INDEX|WITH_POSITION Documents content

  >     load --table Documents
  >     [
  >     ["content"],
  >     ["Groonga is a fast and accurate full text search engine based on inverted index. One of the characteristics of groonga is that a newly registered document instantly appears in search results. Also, groonga allows updates without read locks. These characteristics result in superior performance on real-time applications."],
  >     ["Groonga is also a column-oriented database management system (DBMS). Compared with well-known row-oriented systems, such as MySQL and PostgreSQL, column-oriented systems are more suited for aggregate queries. Due to this advantage, groonga can cover weakness of row-oriented systems."]
  >     ]

  >     select Documents \
  >       --output_columns 'snippet(content, \
  >                                 { \
  >                                    "default_open_tag": "[", \
  >                                    "default_close_tag": "]", \
  >                                    "delimiter_regexp": "\\\\.\\\\s*" \
  >                                 })' \
  >       --match_columns content \
  >       --query "fast performance"
  >     [
  >       [
  >         0,
  >         1337566253.89858,
  >         0.000355720520019531
  >       ],
  >       [
  >         [
  >           [
  >             1
  >           ],
  >           [
  >             [
  >               "snippet",
  >               null
  >             ]
  >           ],
  >           [
  >             [
  >               "Groonga is a [fast] and accurate full text search engine based on inverted index",
  >               "These characteristics result in superior [performance] on real-time applications"
  >             ]
  >           ]
  >         ]
  >       ]
  >     ]

- [window_rank] 新しい関数 `window_rank()` を追加しました。

  - ギャップを含む各レコードの順位を計算できます。通常、順位は、複数のレコードが同じ順位の時は増加しません。例えば、ソートキーの値が 100、 100、 200の場合、これらの順位は 1、 1、 3です。1位のレコードが2つあるので、最後のレコードの順位は2ではなく3です。

    これは、 window_record_number と似ていますが、 window_record_number はギャップを考慮しません。

        table_create Points TABLE_NO_KEY
        column_create Points game COLUMN_SCALAR ShortText
        column_create Points score COLUMN_SCALAR UInt32

        load --table Points
        [
        ["game",  "score"],
        ["game1", 100],
        ["game1", 200],
        ["game1", 100],
        ["game1", 400],
        ["game2", 150],
        ["game2", 200],
        ["game2", 200],
        ["game2", 200]
        ]

        select Points \
          --columns[rank].stage filtered \
          --columns[rank].value 'window_rank()' \
          --columns[rank].type UInt32 \
          --columns[rank].window.sort_keys score \
          --output_columns 'game, score, rank' \
          --sort_keys score
        [
          [
            0,
            1337566253.89858,
            0.000355720520019531
          ],
          [
            [
              [
                8
              ],
              [
                [
                  "game",
                  "ShortText"
                ],
                [
                  "score",
                  "UInt32"
                ],
                [
                  "rank",
                  "UInt32"
                ]
              ],
              [
                "game1",
                100,
                1
              ],
              [
                "game1",
                100,
                1
              ],
              [
                "game2",
                150,
                3
              ],
              [
                "game2",
                200,
                4
              ],
              [
                "game2",
                200,
                4
              ],
              [
                "game1",
                200,
                4
              ],
              [
                "game2",
                200,
                4
              ],
              [
                "game1",
                400,
                8
              ]
            ]
          ]
        ]

- [in_values] テーブル検索時に自動的にキャストするようにしました。

  例えば、 キーの型が `UInt64` のテーブルに `UInt32` の値をロードした場合、Groongaは、 `in_values()` でテーブルを検索するときに自動的に値を `UInt64` にキャストします。ただ、 `in_values(_key, 10)` はこの機能の対象外です。10は、 `Int32` として解釈されるためです。

      table_create Numbers TABLE_HASH_KEY UInt64
      load --table Numbers
      [
      {"_key": 100},
      {"_key": 200},
      {"_key": 300}
      ]

      select Numbers   --output_columns _key   --filter 'in_values(_key, 200, 100)'   --sortby _id
      [[0,0.0,0.0],[[[2],[["_key","UInt64"]],[100],[200]]]]

- [httpd] バンドルしているnginxのバージョンを1.21.3に更新しました。

- [AlmaLinux] AlmaLinux 8 向けのパッケージをサポートしました。

- [Ubuntu] Ubuntu 21.10 (Impish Indri)をサポートしました。

### 修正

- Groongaがコマンドエラー(例えば、filterのシンタックスエラー)発生時に応答を返さない問題を修正しました。

  - これは、 `--output_type apache-arrow` を使っているときのみ発生します。

### 既知の問題

- 現在Groongaには、ベクターカラムに対してデータを大量に追加、削除、更新した際にデータが破損することがある問題があります。

- [ブラウザーベースの管理ツール] 現在Groongaには、レコード一覧の管理モードのチェックボックスにチェックを入れても、非管理モードに入力された検索クエリーが送信されるという問題があります。

- `*<` と `*>` は、filter条件の右辺に `query()` を使う時のみ有効です。もし、以下のように指定した場合、 `*<` と `*>` は `&&` として機能します。

  > - `'content @ "Groonga" *< content @ "Mroonga"'`

- `GRN_II_CURSOR_SET_MIN_ENABLE` が原因でマッチするはずのレコードを返さないことがあります。

## 11.0.7リリース - 2021-09-29

### 改良

- [load] "[int, int,...]" のような文字列を [int, int,...] のような整数のベクターにキャストするようにしました。

  例えば、以下のように、"[1, -2]" のようなベクターを文字列としてロードしたとしても、 [1, -2] のように整数のベクターとして扱います。

  >     table_create Data TABLE_NO_KEY
  >     column_create Data numbers COLUMN_VECTOR Int16
  >     table_create Numbers TABLE_PAT_KEY Int16
  >     column_create Numbers data_numbers COLUMN_INDEX Data numbers

  >     load --table Data
  >     [
  >     {"numbers": "[1, -2]"},
  >     {"numbers": "[-3, 4]"}
  >     ]

  >     dump   --dump_plugins no   --dump_schema no
  >     load --table Data
  >     [
  >     ["_id","numbers"],
  >     [1,[1,-2]],
  >     [2,[-3,4]]
  >     ]

  >     column_create Numbers data_numbers COLUMN_INDEX Data numbers
  >     select Data --filter 'numbers @ -2'
  >     [[0,0.0,0.0],[[[1],[["_id","UInt32"],["numbers","Int16"]],[1,[1,-2]]]]]

  この機能は以下の型をサポートします。

  > - Int8

  > - UInt8

  > - Int16

  > - UInt16

  > - Int32

  > - UInt32

  > - Int64

  > - UInt64

- [load] 文字列として表現されたJSON配列を文字列のベクターとしてロードできるようにしました。

  例えば、以下のように "["hello", "world"]" のような文字列として表現されたJSON配列をロードした場合、 ["hello", "world"] のように2つの要素を持つベクターとして扱います。

      table_create Data TABLE_NO_KEY
      [[0,0.0,0.0],true]
      column_create Data strings COLUMN_VECTOR ShortText
      [[0,0.0,0.0],true]
      table_create Terms TABLE_PAT_KEY ShortText   --normalizer NormalizerNFKC130   --default_tokenizer TokenNgram
      [[0,0.0,0.0],true]
      column_create Terms data_strings COLUMN_INDEX Data strings
      [[0,0.0,0.0],true]
      load --table Data
      [
      {"strings": "[\"Hello\", \"World\"]"},
      {"strings": "[\"Good-bye\", \"World\"]"}
      ]
      [[0,0.0,0.0],2]
      dump   --dump_plugins no   --dump_schema no
      load --table Data
      [
      ["_id","strings"],
      [1,["Hello","World"]],
      [2,["Good-bye","World"]]
      ]

      column_create Terms data_strings COLUMN_INDEX Data strings
      select Data --filter 'strings @ "bye"'
      [
        [
          0,
          0.0,
          0.0
        ],
        [
          [
            [
              1
            ],
            [
              [
                "_id",
                "UInt32"
              ],
              [
                "strings",
                "ShortText"
              ]
            ],
            [
              2,
              [
                "Good-bye",
                "World"
              ]
            ]
          ]
        ]
      ]

  以前のバージョンでは、 "["hello", "world"]" のような文字列として表現されたJSON配列をロードした場合は、 ["["hello", "world"]"] のような一つの要素を持つベクターとして扱っていました。

- [Documentation] 以下の項目についてのドキュメントを追加しました。

  - [column_create] `WEIGHT_FLOAT32` フラグについてのドキュメントを追加しました。

  - [NormalizerNFKC121] `NormalizerNFKC121` についてのドキュメントを追加しました。

  - [NormalizerNFKC130] `NormalizerNFKC130` についてのドキュメントを追加しました。

  - [NormalizerTable] `NormalizerTable` についてのドキュメントを追加しました。

- Groongaが要求する Apache Arrow のバージョンを 3.0.0 に更新しました。[GitHub#1265][Takashi Hashidaさんがパッチ提供]

### 修正

- テーブル作成時に無効なオプションを持つトークナイザーを指定するとメモリーリークする問題を修正しました。

- Hashテーブルに新しいエントリーを追加できなくなることがある問題を修正しました。

  このバグは、Groonga 11.0.6 でのみ発生し、頻繁にデータを追加、削除すると発生することがあります。もし、このバグが発生した場合は、以下の手順を実行することで、この問題を解決できます。

  1. Groongaを11.0.6から11.0.7以降にアップグレードします。

  2. 元のテーブルと同じスキーマを持つ新しいテーブルを作ります。

  3. 元のテーブルから新しいテーブルにデータをコピーします。

- [Windows] メモリー不足によって、新しくファイルのオープンに失敗した時にリソースリークする問題を修正しました。

### 既知の問題

- 現在Groongaには、ベクターカラムに対してデータを大量に追加、削除、更新した際にデータが破損することがある問題があります。

- [ブラウザーベースの管理ツール] 現在Groongaには、レコード一覧の管理モードのチェックボックスにチェックを入れても、非管理モードに入力された検索クエリーが送信されるという問題があります。

- `*<` と `*>` は、filter条件の右辺に `query()` を使う時のみ有効です。もし、以下のように指定した場合、 `*<` と `*>` は `&&` として機能します。

  > - `'content @ "Groonga" *< content @ "Mroonga"'`

- `GRN_II_CURSOR_SET_MIN_ENABLE` が原因でマッチするはずのレコードを返さないことがあります。

### 感謝

- Takashi Hashidaさん

## 11.0.6リリース - 2021-08-29

> 警告

> Groonga 11.0.6 には、Hashテーブルに新しいエントリーを追加できなくなることがある問題があります。

> この問題は、Groonga 11.0.7で修正しました。この問題は、Groonga 11.0.6でのみ発生します。したがって、Groonga 11.0.6をお使いの方は、Groonga 11.0.7以降を使うことを強くおすすめします。

### 改良

- クラッシュ時に自動でリカバリーする機能を追加しました。(実験的な機能です。)

  この機能は実験的な機能です。現状、この機能はまだ安定していません。

  この機能によって、Groongaがクラッシュした時、Groongaはクラッシュした後、最初のデータベースオープン時に自動的にデータベースをリカバリーします。ただ、全てのクラッシュケースで自動的にデータベースをリカバリーできるわけではありません。クラッシュのタイミングによっては、手動でデータベースのリカバリーが必要になります。

  この機能が有効な時、GroongaはWAL(ログ先行書き込み)を実行します。以下のツールを使うことでWALをダンプできますが、現状これらをユーザーが使う必要はありません。

  > - [grndb] `dump-wal` コマンド

  > - `dump-wal.rb` スクリプト

- [cache_limit] `cache_limit 0` を実行したときにキャッシュを削除するようにしました。[GitHub#1224][higchiさんからの報告]

  Groongaは内部的なテーブルにクエリーキャッシュを保存しています。このテーブルは、ハッシュテーブルなので、トータルのキーサイズは最大で4GiBです。そのため、もし多くの巨大なクエリーを実行した場合、トータルのキーサイズの最大値4GiBを超え、Groongaがクエリーをキャッシュできない可能性があります。このようなケースで、 `cache_limit 0` を実行することで、クエリーキャッシュ用のテーブルをクリアーし、Groongaがクエリーキャッシュを保存できるようにします。

### 修正

- 同時期に複数のスレッドで同じオブジェクトをオープンした時に、Groongaがロックを解除しない問題を修正しました。

  同時期に複数のスレッドが同じオブジェクトをオープンすると、最初にオブジェクトを開いたスレッド以外のスレッドは対象のオブジェクトが開かれるまで待ちます。この時、対象のオブジェクトが開かれるのを待っているスレッドもロックを取得しますが、これらのロックは解放されません。したがって、Groongaのプロセスを再起動するまでこれらのロックが残り、その新しいスレッドは、Groongaが再起動するまで、そのオブジェクトを開けません。

  ただ、スレッドがオブジェクトを開く時間は非常に短いため、このバグは滅多に起こりません。

- [query_parallel_or] `query()` と結果が異なることがある問題を修正しました。

  例えば、 `query("tags || tags2", "beginner man")` とした場合は、以下のレコードはマッチしますが、`query_parallel_or("tags || tags2", "beginner man")` とした場合は、今までは、以下のレコードはマッチしませんでした。

  - `{"_key": "Bob", "comment": "Hey!", "tags": ["expert", "man"], "tags2": ["beginner"]}`

  今回の変更によって、 `query_parallel_or("tags || tags2", "beginner man")` を使った場合であっても、上記のレコードがマッチするようになりました。

### 既知の問題

- 現在Groongaには、ベクターカラムに対してデータを大量に追加、削除、更新した際にデータが破損することがある問題があります。

- [ブラウザーベースの管理ツール] 現在Groongaには、レコード一覧の管理モードのチェックボックスにチェックを入れても、非管理モードに入力された検索クエリーが送信されるという問題があります。

- `*<` と `*>` は、filter条件の右辺に `query()` を使う時のみ有効です。もし、以下のように指定した場合、 `*<` と `*>` は `&&` として機能します。

  > - `'content @ "Groonga" *< content @ "Mroonga"'`

- `GRN_II_CURSOR_SET_MIN_ENABLE` が原因でマッチするはずのレコードを返さないことがあります。

### 感謝

- higchiさん

## 11.0.5リリース - 2021-07-29

### 改良

- [ノーマライザー] ノーマライザーを複数指定できるようになりました。

  テーブル作成時に `--normalizers` オプションを使うことで、複数のノーマライザーを指定できます。互換性のため、既存の `--normalizer` を使っても複数のノーマライザーを指定できます。

  Groonga 11.0.4 でノーマライザーをカスタマイズするための `NormalizerTable` を追加しました。この `NormalizerTable` と既存のノーマライザーを組み合わせることでより柔軟な制御ができます。

  例えば、この機能は、以下のようなケースで有用です。

  > - 電話番号を検索します。ただし、データはOCRで手書きのデータを取り込みます。OCRは数字と文字列をご認識することがあります。(例えば、 5とS など)

  具体的には以下の通りです。

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

      table_create Tels TABLE_NO_KEY
      column_create Tels tel COLUMN_SCALAR ShortText

      table_create TelsIndex TABLE_PAT_KEY ShortText \
        --normalizers 'NormalizerNFKC130("unify_hyphen_and_prolonged_sound_mark", true), \
                       NormalizerTable("column", "Normalizations.normalized")' \
        --default_tokenizer 'TokenNgram("loose_symbol", true, "loose_blank", true)'
      column_create TelsIndex tel_index COLUMN_INDEX|WITH_SECTION Tels tel

      load --table Tels
      [
      {"tel": "03-4S-1234"}
      {"tel": "03-45-9876"}
      ]

      select --table Tels \
        --filter 'tel @ "03-45-1234"'
      [
        [
          0,
          1625227424.560146,
          0.0001730918884277344
        ],
        [
          [
            [
              1
            ],
            [
              [
                "_id",
                "UInt32"
              ],
              [
                "tel",
                "ShortText"
              ]
            ],
            [
              1,
              "03-4S-1234"
            ]
          ]
        ]
      ]

  既存のノーマライザーでは、このようなケースには対応できませんでしたが、このリリースから既存のノーマライザーと `NormalizerTable` を組み合わせることで、このようなケースにも対応できます。

- [query_parallel_or][query] シーケンシャルサーチのしきい値をカスタマイズできるようにしました。

  以下のオプションを使うことで、シーケンシャルサーチを使うかどうかのしきい値をクエリーごとにカスタマイズできます。

  > - `{"max_n_enough_filtered_records": xx}`

  >   `max_n_enough_filtered_records` は、レコード数を指定します。 `query` または、 `query_parallel_or` で、この値以下までレコードが絞り込めそうな場合、シーケンシャルサーチを使います。

  > - `{"enough_filtered_ratio": x.x}`

  >   `enough_filtered_ratio` は、全体に占める割合を指定します。 `query` または、 `query_parallel_or` で、この割合以下までレコードが絞り込めそうな場合、シーケンシャルサーチを使います。例えば、`{"enough_filtered_ratio": 0.5}` とした場合、 `query` または `query_parallel_or` で全体の半分まで絞り込めそうな場合はシーケンシャルサーチを使います。

  具体的には以下の通りです。

  >     table_create Products TABLE_NO_KEY
  >     column_create Products name COLUMN_SCALAR ShortText

  >     table_create Terms TABLE_PAT_KEY ShortText --normalizer NormalizerAuto
  >     column_create Terms products_name COLUMN_INDEX Products name

  >     load --table Products
  >     [
  >     ["name"],
  >     ["Groonga"],
  >     ["Mroonga"],
  >     ["Rroonga"],
  >     ["PGroonga"],
  >     ["Ruby"],
  >     ["PostgreSQL"]
  >     ]

  >     select \
  >       --table Products \
  >       --filter 'query("name", "r name:Ruby", {"enough_filtered_ratio": 0.5})'

  >     table_create Products TABLE_NO_KEY
  >     column_create Products name COLUMN_SCALAR ShortText

  >     table_create Terms TABLE_PAT_KEY ShortText --normalizer NormalizerAuto
  >     column_create Terms products_name COLUMN_INDEX Products name

  >     load --table Products
  >     [
  >     ["name"],
  >     ["Groonga"],
  >     ["Mroonga"],
  >     ["Rroonga"],
  >     ["PGroonga"],
  >     ["Ruby"],
  >     ["PostgreSQL"]
  >     ]

  >     select \
  >       --table Products \
  >       --filter 'query("name", "r name:Ruby", {"max_n_enough_filtered_records": 10})'

- [between][in_values] シーケンシャルサーチのしきい値をカスタマイズできるようにしました。

  [between] と [in_values] は、検索対象のレコードが十分に絞り込まれている時に、シーケンシャルサーチに切り替える機能があります。

  `GRN_IN_VALUES_TOO_MANY_INDEX_MATCH_RATIO` / `GRN_BETWEEN_TOO_MANY_INDEX_MATCH_RATIO` の値は、Groongaがシーケンシャルサーチを実行するかインデックスを使った検索をするかのしきい値として使われます。

  今までは、以下の環境変数でのみカスタマイズ可能でした。

  `in_values()`:

      # Don't use auto sequential search
      GRN_IN_VALUES_TOO_MANY_INDEX_MATCH_RATIO=-1
      # Set threshold to 0.02
      GRN_IN_VALUES_TOO_MANY_INDEX_MATCH_RATIO=0.02

  `between()`:

      # Don't use auto sequential search
      GRN_BETWEEN_TOO_MANY_INDEX_MATCH_RATIO=-1
      # Set threshold to 0.02
      GRN_BETWEEN_TOO_MANY_INDEX_MATCH_RATIO=0.02

  環境変数によるカスタマイズは、すべてのクエリーに対して適用されますが、この機能を使うことで、クエリーごとにしきい値を指定できます。

  具体的には以下の通りです。 `{"too_many_index_match_ratio": x.xx}` オプションでしきい値を指定できます。このオプションの値の型は `double` 型です。

      table_create Memos TABLE_HASH_KEY ShortText
      column_create Memos timestamp COLUMN_SCALAR Time

      table_create Times TABLE_PAT_KEY Time
      column_create Times memos_timestamp COLUMN_INDEX Memos timestamp

      load --table Memos
      [
      {"_key": "001", "timestamp": "2014-11-10 07:25:23"},
      {"_key": "002", "timestamp": "2014-11-10 07:25:24"},
      {"_key": "003", "timestamp": "2014-11-10 07:25:25"},
      {"_key": "004", "timestamp": "2014-11-10 07:25:26"},
      {"_key": "005", "timestamp": "2014-11-10 07:25:27"},
      {"_key": "006", "timestamp": "2014-11-10 07:25:28"},
      {"_key": "007", "timestamp": "2014-11-10 07:25:29"},
      {"_key": "008", "timestamp": "2014-11-10 07:25:30"},
      {"_key": "009", "timestamp": "2014-11-10 07:25:31"},
      {"_key": "010", "timestamp": "2014-11-10 07:25:32"},
      {"_key": "011", "timestamp": "2014-11-10 07:25:33"},
      {"_key": "012", "timestamp": "2014-11-10 07:25:34"},
      {"_key": "013", "timestamp": "2014-11-10 07:25:35"},
      {"_key": "014", "timestamp": "2014-11-10 07:25:36"},
      {"_key": "015", "timestamp": "2014-11-10 07:25:37"},
      {"_key": "016", "timestamp": "2014-11-10 07:25:38"},
      {"_key": "017", "timestamp": "2014-11-10 07:25:39"},
      {"_key": "018", "timestamp": "2014-11-10 07:25:40"},
      {"_key": "019", "timestamp": "2014-11-10 07:25:41"},
      {"_key": "020", "timestamp": "2014-11-10 07:25:42"},
      {"_key": "021", "timestamp": "2014-11-10 07:25:43"},
      {"_key": "022", "timestamp": "2014-11-10 07:25:44"},
      {"_key": "023", "timestamp": "2014-11-10 07:25:45"},
      {"_key": "024", "timestamp": "2014-11-10 07:25:46"},
      {"_key": "025", "timestamp": "2014-11-10 07:25:47"},
      {"_key": "026", "timestamp": "2014-11-10 07:25:48"},
      {"_key": "027", "timestamp": "2014-11-10 07:25:49"},
      {"_key": "028", "timestamp": "2014-11-10 07:25:50"},
      {"_key": "029", "timestamp": "2014-11-10 07:25:51"},
      {"_key": "030", "timestamp": "2014-11-10 07:25:52"},
      {"_key": "031", "timestamp": "2014-11-10 07:25:53"},
      {"_key": "032", "timestamp": "2014-11-10 07:25:54"},
      {"_key": "033", "timestamp": "2014-11-10 07:25:55"},
      {"_key": "034", "timestamp": "2014-11-10 07:25:56"},
      {"_key": "035", "timestamp": "2014-11-10 07:25:57"},
      {"_key": "036", "timestamp": "2014-11-10 07:25:58"},
      {"_key": "037", "timestamp": "2014-11-10 07:25:59"},
      {"_key": "038", "timestamp": "2014-11-10 07:26:00"},
      {"_key": "039", "timestamp": "2014-11-10 07:26:01"},
      {"_key": "040", "timestamp": "2014-11-10 07:26:02"},
      {"_key": "041", "timestamp": "2014-11-10 07:26:03"},
      {"_key": "042", "timestamp": "2014-11-10 07:26:04"},
      {"_key": "043", "timestamp": "2014-11-10 07:26:05"},
      {"_key": "044", "timestamp": "2014-11-10 07:26:06"},
      {"_key": "045", "timestamp": "2014-11-10 07:26:07"},
      {"_key": "046", "timestamp": "2014-11-10 07:26:08"},
      {"_key": "047", "timestamp": "2014-11-10 07:26:09"},
      {"_key": "048", "timestamp": "2014-11-10 07:26:10"},
      {"_key": "049", "timestamp": "2014-11-10 07:26:11"},
      {"_key": "050", "timestamp": "2014-11-10 07:26:12"}
      ]

      select Memos \
        --filter '_key == "003" && \
                  between(timestamp, \
                          "2014-11-10 07:25:24", \
                          "include", \
                          "2014-11-10 07:27:26", \
                          "exclude", \
                          {"too_many_index_match_ratio": 0.03})'

      table_create Tags TABLE_HASH_KEY ShortText

      table_create Memos TABLE_HASH_KEY ShortText
      column_create Memos tag COLUMN_SCALAR Tags

      load --table Memos
      [
      {"_key": "Rroonga is fast!", "tag": "Rroonga"},
      {"_key": "Groonga is fast!", "tag": "Groonga"},
      {"_key": "Mroonga is fast!", "tag": "Mroonga"},
      {"_key": "Groonga sticker!", "tag": "Groonga"},
      {"_key": "Groonga is good!", "tag": "Groonga"}
      ]

      column_create Tags memos_tag COLUMN_INDEX Memos tag

      select \
        Memos \
        --filter '_id >= 3 && \
                  in_values(tag, \
                           "Groonga", \
                           {"too_many_index_match_ratio": 0.7})' \
        --output_columns _id,_score,_key,tag

- [between] `GRN_EXPR_OPTIMIZE=yes` をサポートしました。

  `between()` で、条件式の評価順序の最適化をサポートしました。

- [query_parallel_or][query] match_columns を vector で指定できるようにしました。[GitHub#1238][naoaさんがパッチ提供]

  以下のように、 `query` と `query_parallel_or` の `match_columns` に vector を使えます。

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

      table_create Terms TABLE_PAT_KEY ShortText \
        --default_tokenizer TokenNgram \
        --normalizer NormalizerNFKC130
      column_create Terms name COLUMN_INDEX|WITH_POSITION Users name
      column_create Terms memo COLUMN_INDEX|WITH_POSITION Users memo
      column_create Terms tag COLUMN_INDEX|WITH_POSITION Users tag

      load --table Users
      [
      {"name": "Alice", "memo": "Groonga user", "tag": "Groonga"},
      {"name": "Bob",   "memo": "Rroonga user", "tag": "Rroonga"}
      ]

      select Users \
        --output_columns _score,name \
        --filter 'query(["name * 100", "memo", "tag * 10"], \
                        "Alice OR Groonga")'

- [select] 前方一致検索でセクションと重みをサポートしました。[GitHub#1240][naoaさんがパッチ提供]

  前方一致検索でマルチカラムインデックスと、スコアーの調整ができます。

      table_create Memos TABLE_NO_KEY
      column_create Memos title COLUMN_SCALAR ShortText
      column_create Memos tags COLUMN_VECTOR ShortText

      table_create Terms TABLE_PAT_KEY ShortText
      column_create Terms index COLUMN_INDEX|WITH_SECTION Memos title,tags

      load --table Memos
      [
      {"title": "Groonga", "tags": ["Groonga"]},
      {"title": "Rroonga", "tags": ["Groonga", "Rroonga", "Ruby"]},
      {"title": "Mroonga", "tags": ["Groonga", "Mroonga", "MySQL"]}
      ]

      select Memos \
        --match_columns "Terms.index.title * 2" \
        --query 'G*' \
        --output_columns title,tags,_score
      [
        [
          0,
          0.0,
          0.0
        ],
        [
          [
            [
              1
            ],
            [
              [
                "title",
                "ShortText"
              ],
              [
                "tags",
                "ShortText"
              ],
              [
                "_score",
                "Int32"
              ]
            ],
            [
              "Groonga",
              [
                "Groonga"
              ],
              2
            ]
          ]
        ]
      ]

- [grndb] `grndb recover` で使用したオブジェクトを即時閉じるようにしました。

  これにより、メモリ消費を抑制できます。おそらくパフォーマンスは低下していますが、許容可能な低下です。

  `grndb check` はまだ、使用したオブジェクトを即時閉じないので注意してください。

- [query_parallel_or][query] 以下のように、 `match_columns` に `scorer_tf_idf` を指定できるようにしました。

      table_create Tags TABLE_HASH_KEY ShortText

      table_create Users TABLE_HASH_KEY ShortText
      column_create Users tags COLUMN_VECTOR Tags

      load --table Users
      [
      {"_key": "Alice",
       "tags": ["beginner", "active"]},
      {"_key": "Bob",
       "tags": ["expert", "passive"]},
      {"_key": "Chris",
       "tags": ["beginner", "passive"]}
      ]

      column_create Tags users COLUMN_INDEX Users tags

      select Users \
        --output_columns _key,_score \
        --sort_keys _id \
        --command_version 3 \
        --filter 'query_parallel_or("scorer_tf_idf(tags)", \
                                    "beginner active")'
      {
        "header": {
          "return_code": 0,
          "start_time": 0.0,
          "elapsed_time": 0.0
        },
        "body": {
          "n_hits": 1,
          "columns": [
            {
              "name": "_key",
              "type": "ShortText"
            },
            {
              "name": "_score",
              "type": "Float"
            }
          ],
          "records": [
            [
              "Alice",
              2.098612308502197
            ]
          ]
        }
      }

- [query_expand] 展開後の語の重みを操作できるようにしました。

  展開後の語に対して、重みを指定できます。

  スコアーを増やしたい場合は、 `>` を使います。スコアーを減らしたい場合は、 `<` を指定します。

  数字でスコアーの量を指定できます。負の数も指定できます。

      table_create TermExpansions TABLE_NO_KEY
      column_create TermExpansions term COLUMN_SCALAR ShortText
      column_create TermExpansions expansions COLUMN_VECTOR ShortText

      load --table TermExpansions
      [
      {"term": "Rroonga", "expansions": ["Rroonga", "Ruby Groonga"]}
      ]

      query_expand TermExpansions "Groonga <-0.2Rroonga Mroonga" \
        --term_column term \
        --expanded_term_column expansions
      [[0,0.0,0.0],"Groonga <-0.2((Rroonga) OR (Ruby Groonga)) Mroonga"]

- [httpd] バンドルしているnginxのバージョンを1.21.1に更新しました。

- バンドルしているApache Arrowを5.0.0に更新しました。

- [Ubuntu] Ubuntu 20.10 (Groovy Gorilla)サポートをやめました。

  - Ubuntu 20.10 は、2021年7月22日でEOLとなったためです。

### 修正

- [query_parallel_or][query] `query_options` とその他のオプションを指定すると、その他のオプションが無視される問題を修正しました。

  例えば、以下のケースでは、 `"default_operator": "OR"` オプションは無視されていました。

      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": "and"},
      {"content": "Good-bye"}
      ]

      select Memos \
        --filter 'query_parallel_or( \
                    "content", \
                    "Hello and", \
                    {"default_operator": "OR", \
                     "options": {"TokenFilterStopWord.enable": false}})' \
        --match_escalation_threshold -1 \
        --sort_keys -_score
      [
        [
          0,
          0.0,
          0.0
        ],
        [
          [
            [
              1
            ],
            [
              [
                "_id",
                "UInt32"
              ],
              [
                "content",
                "ShortText"
              ]
            ],
            [
              2,
              "Hello and Good-bye"
            ]
          ]
        ]
      ]

### 既知の問題

- 現在Groongaには、ベクターカラムに対してデータを大量に追加、削除、更新した際にデータが破損することがある問題があります。

- [ブラウザーベースの管理ツール] 現在Groongaには、レコード一覧の管理モードのチェックボックスにチェックを入れても、非管理モードに入力された検索クエリーが送信されるという問題があります。

- `*<` と `*>` は、filter条件の右辺に `query()` を使う時のみ有効です。もし、以下のように指定した場合、 `*<` と `*>` は `&&` として機能します。

  > - `'content @ "Groonga" *< content @ "Mroonga"'`

- 多くのデータを削除し、同じデータを再度loadすることを繰り返すと、Groongaがヒットすべきレコードを返さないことがあります。

### 感謝

- naoaさん

## 11.0.4リリース - 2021-06-29

### 改良

- [Normalizer] カスタマイズされたノーマライザーを使えるようになりました。

  この機能を使うためにノーマライズ用のテーブルを定義し、このテーブルを使ってノーマライズします。つまり、カスタマイズされたノーマライザーを使うことができます。

  例えば、以下の例では、 "S" を "5" に正規化するよう定義しています。`Substitutions` テーブルが正規化用のテーブルです。

  >     table_create Substitutions TABLE_PAT_KEY ShortText
  >     column_create Substitutions substituted COLUMN_SCALAR ShortText
  >     load --table Substitutions
  >     [
  >     {"_key": "S", "substituted": "5"}
  >     ]

  >     table_create TelLists TABLE_NO_KEY
  >     column_create TelLists tel COLUMN_SCALAR ShortText

  >     table_create Terms TABLE_HASH_KEY ShortText \
  >       --default_tokenizer TokenNgram \
  >       --normalizer 'NormalizerTable("column", "Substitutions.substituted", \
  >                                     "report_source_offset", true)'
  >     column_create Terms tel_index COLUMN_INDEX|WITH_POSITION TelLists tel

  >     load --table TelLists
  >     [
  >     {"tel": "03-4S-1234"}
  >     ]

  >     select TelLists --filter 'tel @ "03-45-1234"'
  >     [
  >       [
  >         0,
  >         1624686303.538532,
  >         0.001319169998168945
  >       ],
  >       [
  >         [
  >           [
  >             1
  >           ],
  >           [
  >             [
  >               "_id",
  >               "UInt32"
  >             ],
  >             [
  >               "tel",
  >               "ShortText"
  >             ]
  >           ],
  >           [
  >             1,
  >             "03-4S-1234"
  >           ]
  >         ]
  >       ]
  >     ]

  例えば、手書きの文字を取り込む際に誤認識されやすい語を定義できます。そうすることで、誤ったデータを正規化して正しいデータにできます。

  この正規化用のテーブルを更新した場合は、インデックスの再構築が必要なことに注意してください。

- 新しいコマンド `object_warm` を追加しました。

  このコマンドは、GroongaのDBをOSのページキャッシュに乗せます。

  OS起動後、Groongaを一度も起動していない場合、GroongaのDBはOSのページキャッシュ上に存在しません。そのため、Groongaに対する最初の操作は遅くなります。

  予めこのコマンドを実行した場合、Groongaへの最初の操作は速くなります。Linuxでは、 `cat *.db > dev/null` で同等のことができますが、Windowsでは、いままで、同様のことはできませんでした。

  このコマンドを使うことで、LinuxでもWindowsでもGroongaのDBをOSのページキャッシュへ乗せることができます。また、テーブル、カラム、インデックス単位でも同様のことができます。したがって、よく使うテーブルやカラム、インデックスのみをOSのページキャッシュに乗せることができます。

  このコマンドは、以下のように様々な対象に対して実行できます。

  > - `object_warm --name index_name` と指定した場合は、指定したインデックスがOSのページキャッシュへ転送されます。

  > - `object_warm --name column_name` と指定した場合は、指定したカラムがOSののページキャッシュへ転送されます。

  > - `object_warm --name table_name` と指定した場合は、指定したテーブルをOSのページキャッシュへ転送します。

  > - `object_warm` と指定した場合は、GroongaのDB全体がOSのページキャッシュへ転送されます。

  ただ、メモリーに空きスペースが無い場合は、このコマンドは効果がないことに注意してください。

- [select] `--filter` 内で特定のレコードのスコアーを調整できるようにしました。

  `*~` という演算子を使うことで、特定のレコードのスコアーを調整できます。`*~` は `&&` や `||` と同じ論理演算子です。したがって、 `&&` や `||` と同じように使えます。`*~` のデフォルトの重みは -1 です。

  したがって、例えば、 `'content @ "Groonga" *~ content @ "Mroonga"'` は以下の操作を意味します。

  > 1. `'content @ "Groonga"` と `content @ "MySQL"` にマッチしたレコードを抽出します。

  > 2. 以下のようにスコアーを追加します。

  >    1. `'content @ "Groonga"` のスコアーを計算します。

  >    2. `content @ "Mroonga"'` のスコアーを計算します。

  >    3. bのスコアーを -1 倍します。

  >    4. このレコードのスコアーは a + b です。したがって、 aのスコアー 1 で bのスコアーが1 の場合、このレコードのスコアーは 1 + (1 * -1) = 0 です。

  また、 `*~${score_quantity}` とすることで、スコアーの量を指定できます。

  具体的には、 以下の条件( `'content @ "Groonga" *~2.5 content @ "MySQL"'` ) にマッチしたレコードのスコアーを調整します。

  >     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
  >     column_create Terms index COLUMN_INDEX|WITH_POSITION Memos content

  >     load --table Memos
  >     [
  >     {"content": "Groonga is a full text search engine."},
  >     {"content": "Rroonga is the Ruby bindings of Groonga."},
  >     {"content": "Mroonga is a MySQL storage engine based of Groonga."}
  >     ]

  >     select Memos \
  >       --command_version 3 \
  >       --filter 'content @ "Groonga" *~2.5 content @ "Mroonga"' \
  >       --output_columns 'content, _score' \
  >       --sort_keys -_score,_id
  >     {
  >       "header": {
  >         "return_code": 0,
  >         "start_time": 1624605205.641078,
  >         "elapsed_time": 0.002965450286865234
  >       },
  >       "body": {
  >         "n_hits": 3,
  >         "columns": [
  >           {
  >             "name": "content",
  >             "type": "ShortText"
  >           },
  >           {
  >             "name": "_score",
  >             "type": "Float"
  >           }
  >         ],
  >         "records": [
  >           [
  >             "Groonga is a full text search engine.",
  >             1.0
  >           ],
  >           [
  >             "Rroonga is the Ruby bindings of Groonga.",
  >             1.0
  >           ],
  >           [
  >             "Mroonga is a MySQL storage engine based of Groonga.",
  >             -1.5
  >           ]
  >         ]
  >       }
  >     }

  adjuster を使っても同様のことができます。adjuster を使う場合、アプリケーション上で、 `--filter` 条件と `--adjuster` 条件を作る必要がありますが、この改良で、 `--filter` 条件のみを作成すればよくなりました。

  以下のように、 `query()` を使って、filter条件を記述することもできます。

  > - `--filter 'content @ "Groonga" *~2.5 content @ "Mroonga"'`

- [select] 重み付き `&&` をサポートしました。

  `*<` と `*>` を使うことで、重み付きの `&&` を使えます。`*<` のデフォルトの重みは 0.5です。 `*>` のデフォルトの重みは 2.0 です。

  `*<${score_quantity}` や `*>${score_quantity}` とすることで、スコアーの量を指定できます。また、 `*<${score_quantity}` と指定した場合は、 ${score_quantity} の正負の符号が反転します。

  例えば、 `'content @ "Groonga" *<2.5 query("content", "MySQL")'` は以下の操作を意味します。

  > 1. `'content @ "Groonga"` と `content @ "MySQL"` にマッチしたレコードを抽出します。

  > 2. 以下のようにスコアーを追加します。

  >    1. `'content @ "Groonga"` のスコアーを計算します。

  >    2. `query("content", "MySQL")` のスコアーを計算します。

  >    3. bのスコアーは、 `*<` によって -2.5倍されます。

  >    4. このレコードのスコアーは a + b です。したがって、 aのスコアー 1 で bのスコアーが1 の場合、このレコードのスコアーは 1 + (1 * -2.5) = −1.5 です。

  具体的には、 以下の条件( `'content @ "Groonga" *~2.5 query("content", "MySQL")'` にマッチしたレコードのスコアーを調整します。

  >     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
  >     column_create Terms index COLUMN_INDEX|WITH_POSITION Memos content

  >     load --table Memos
  >     [
  >     {"content": "Groonga is a full text search engine."},
  >     {"content": "Rroonga is the Ruby bindings of Groonga."},
  >     {"content": "Mroonga is a MySQL storage engine based of Groonga."}
  >     ]

  >     select Memos \
  >       --command_version 3 \
  >       --filter 'content @ "Groonga" *<2.5 query("content", "Mroonga")' \
  >       --output_columns 'content, _score' \
  >       --sort_keys -_score,_id
  >     {
  >       "header": {
  >         "return_code": 0,
  >         "start_time": 1624605205.641078,
  >         "elapsed_time": 0.002965450286865234
  >       },
  >       "body": {
  >         "n_hits": 3,
  >         "columns": [
  >           {
  >             "name": "content",
  >             "type": "ShortText"
  >           },
  >           {
  >             "name": "_score",
  >             "type": "Float"
  >           }
  >         ],
  >         "records": [
  >           [
  >             "Groonga is a full text search engine.",
  >             1.0
  >           ],
  >           [
  >             "Rroonga is the Ruby bindings of Groonga.",
  >             1.0
  >           ],
  >           [
  >             "Mroonga is a MySQL storage engine based of Groonga.",
  >             -1.5
  >           ]
  >         ]
  >       }
  >     }

- [ログ] 標準出力、標準エラー出力への出力をサポートしました。

  [プロセスログ] と [クエリーログ] が標準出力と標準エラー出力への出力をサポートしました。

  > - `--log-path -` や `--query-log-path -` と指定した場合、Groongaはログを標準出力に出力します。

  > - `--log-path +` や `--query-log-path +` と指定した場合、Groongaはログを標準エラー出力に出力します。

  [プロセスログ] はGroongaの動作全てに関することのログです。 [クエリーログ] は、クエリー処理に関することだけのログです。

  この機能はDocker上でGroongaを実行する際に有用です。Dockerは標準で標準出力と標準エラー出力を記録する機能を持っています。したがって、Groongaのログを取得するために、Dockerの環境にログインする必要がなくなります。

  例えば、この機能は、以下のようなケースで有用です。

  > - Docker上のGroongaのスロークエリーを解析したい場合。

  >   Groonga起動時に `--query-log-path -` と指定している場合、以下のコマンドを実行するだけでスロークエリーを解析できます。

  >   > - `docker logs ${container_name} | groonga-query-log-analyze`

  このように、 Groonga上のDockerから出力したクエリーログを使って、簡単にスロークエリの解析ができます。

- [ドキュメント] `string_substring` に不足している内容を追加しました。[Github#1209][Takashi Hashidaさんがパッチ提供]

### 既知の問題

- 現在Groongaには、ベクターカラムに対してデータを大量に追加、削除、更新した際にデータが破損することがある問題があります。

- [ブラウザーベースの管理ツール] 現在Groongaには、レコード一覧の管理モードのチェックボックスにチェックを入れても、非管理モードに入力された検索クエリーが送信されるという問題があります。

- `*<` と `*>` は、filter条件の右辺に `query()` を使う時のみ有効です。もし、以下のように指定した場合、 `*<` と `*>` は `&&` として機能します。

  > - `'content @ "Groonga" *< content @ "Mroonga"'`

### 感謝

- Takashi Hashidaさん

## 11.0.3リリース - 2021-05-29

### 改良

- [query] クエリー毎に `TokenFilterStem` を無効にできるようになりました。

  - `TokenFilterStem` は語幹を使った検索ができます。例えば `develop` も `developing` も `developed` も `develops` も、すべてステミングすると `develop` になります。そのため、 `develops` というクエリーで `develop` も `developing` も `developed` も検索できます。

  - 今回のリリースでは、以下のように特定のクエリーでのみ `TokenFilterStem` を無効にして検索できるようになりました。

        plugin_register token_filters/stem

        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 'TokenFilterStem("keep_original", true)'
        column_create Terms memos_content COLUMN_INDEX|WITH_POSITION Memos content

        load --table Memos
        [
        {"content": "I develop Groonga"},
        {"content": "I'm developing Groonga"},
        {"content": "I developed Groonga"}
        ]

        select Memos \
          --match_columns content \
          --query '"developed groonga"' \
          --query_options '{"TokenFilterStem.enable": false}'
        [
          [
            0,
            0.0,
            0.0
          ],
          [
            [
              [
                1
              ],
              [
                [
                  "_id",
                  "UInt32"
                ],
                [
                  "content",
                  "ShortText"
                ]
              ],
              [
                3,
                "I developed Groonga"
              ]
            ]
          ]
        ]

  - この機能は、通常は語幹を使った検索がしたいが、時々、以下のように(ステミングされていない)正確な語で検索したいときに有用です。

    - ステミングされた語を使った検索だとGroongaが大量の検索結果を返す場合。

    - `TokenFilerStem` が間違ったステミング結果を返す場合。

    - (ステミングされていない)正確な語を含むレコードのみを検索したい場合。

- [query] クエリー毎に `TokenFilterStopWord` を無効にできるようになりました。

  - `TokenFilterStopWord` は、予め登録したストップワードを検索から除外します。これは、 `and` や `is` などの頻出語を無視することで検索ノイズを減らすために使います。

  - ただ、ときどき、特定のクエリーでのみこれらの語を含めて検索したいときがあります。今回のリリースでは、以下のように特定のクエリーでのみ `TokenFilterStopWord` を無効にして検索できるようになりました。

        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 \
          --match_columns content \
          --query "Hello and" \
          --query_options '{"TokenFilterStopWord.enable": false}' \
          --match_escalation_threshold -1 \
          --sort_keys -_score
        [
          [
            0,
            0.0,
            0.0
          ],
          [
            [
              [
                1
              ],
              [
                [
                  "_id",
                  "UInt32"
                ],
                [
                  "content",
                  "ShortText"
                ]
              ],
              [
                2,
                "Hello and Good-bye"
              ]
            ]
          ]
        ]

  - 上記の例では、 `--query-options` を使って、 `TokenFilterStopWord.enable` を指定していますが、以下のように `{"options": {"TokenFilterStopWord.enable": false}}` を使っても指定できます。

        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("content", \
                          "Hello and", \
                          {"options": {"TokenFilterStopWord.enable": false}})' \
          --match_escalation_threshold -1 \
          --sort_keys -_score
        [
          [
            0,
            0.0,
            0.0
          ],
          [
            [
              [
                1
              ],
              [
                [
                  "_id",
                  "UInt32"
                ],
                [
                  "content",
                  "ShortText"
                ]
              ],
              [
                2,
                "Hello and Good-bye"
              ]
            ]
          ]
        ]

  - この機能は、よく使われる語を含めて検索しないとGroongaが正しい結果を返さない時に便利です。(例えば、曲名や店名等を検索する場合です。)

- [ノーマライザー][NormalizerNFKC] 新しいオプション `remove_new_line` を追加しました。

  - データを格納するテーブルのキーを正規化したい場合、そのテーブルにノーマライザーを設定しますが、通常ノーマライザーは改行を削除します。

  - ノーマライザーが改行を削除してしまうと、Groongaは改行のみのキーを扱えません。

  - このオプションを使うことで、改行のみのデータをキーとして登録できます。

- [string_slice] 新しい関数 `string_slice()` を追加しました。 [Github#1177][Takashi Hashidaさんがパッチ提供]

  - `string_slice()` は、文字列の部分文字列を抽出します。

  - この関数を使うには、 `functions/string` プラグインの登録が必要です。

  - 以下のように、引数によって２つの異なる抽出方法を使えます。

    - 位置を使った抽出:

          plugin_register functions/string
          table_create Memos TABLE_HASH_KEY ShortText

          load --table Memos
          [
            {"_key": "Groonga"}
          ]
          select Memos --output_columns '_key, string_slice(_key, 2, 3)'
          [
            [
              0,
              1337566253.89858,
              0.000355720520019531
            ],
            [
              [
                [
                  1
                ],
                [
                  [
                    "_key",
                    "ShortText"
                  ],
                  [
                    "string_slice",
                    null
                  ]
                ],
                [
                  "Groonga",
                  "oon"
                ]
              ]
            ]
          ]

    - 正規表現を使った抽出:

          plugin_register functions/string
          table_create Memos TABLE_HASH_KEY ShortText

          load --table Memos
          [
            {"_key": "Groonga"}
          ]
          select Memos --output_columns '_key, string_slice(_key, "(Gro+)(.*)", 2)'
          [
            [p
              0,
              1337566253.89858,
              0.000355720520019531
            ],
            [
              [
                [
                  1
                ],
                [
                  [
                    "_key",
                    "ShortText"
                  ],
                  [
                    "string_slice",
                    null
                  ]
                ],
                [
                  "Groonga",
                  "nga"
                ]
              ]
            ]
          ]

- [Ubuntu] Ubuntu 16.04 LTS (Xenial Xerus)のサポートをやめました。

- Visual Studio 用の EditorConfig を追加しました。[GitHub#1191][Takashi Hashidaさんがパッチ提供]

  - 多くの設定は、Visual Studio 専用です。

- [httpd] バンドルしているnginxのバージョンを1.20.1に更新しました。

  - CVE-2021-23017のセキュリティの修正が含まれています。

### 修正

- オプションをサポートしているトークナイザーやノーマライザー、トークンフィルターが使われている際、多くの検索クエリーを送信するとGroongaが応答を返さなくなることがある問題を修正しました。

### 既知の問題

- 現在Groongaには、ベクターカラムに対してデータを大量に追加、削除、更新した際にデータが破損することがある問題があります。

- [ブラウザーベースの管理ツール] 現在Groongaには、レコード一覧の管理モードのチェックボックスにチェックを入れても、非管理モードに入力された検索クエリーが送信されるという問題があります。

### 感謝

- Takashi Hashidaさん

## 11.0.2リリース - 2021-05-10

### 改良

- [Documentation] `ruby_load` コマンドのリファレンスを削除しました。　[GitHub#1172][Anthony M. Cookさんがパッチ提供]

  - このコマンドはすでに削除されているためです。

- [Debian GNU/Linux] Debian 11(Bullseye) をサポートしました。

- [select] `--post_filter` をサポートしました。

  - 以下のように、 `filtered` ステージの動的カラムに対して `post_filter` を使ってフィルターできます。

        table_create Items TABLE_NO_KEY
        column_create Items price COLUMN_SCALAR UInt32

        load --table Items
        [
        {"price": 100},
        {"price": 150},
        {"price": 200},
        {"price": 250},
        {"price": 300}
        ]

        select Items \
          --filter "price >= 150" \
          --columns[price_with_tax].stage filtered \
          --columns[price_with_tax].type UInt32 \
          --columns[price_with_tax].flags COLUMN_SCALAR \
          --columns[price_with_tax].value "price * 1.1" \
          --post_filter "price_with_tax <= 250"
        [
          [
            0,
            0.0,
            0.0
          ],
          [
            [
              [
                2
              ],
              [
                [
                  "_id",
                  "UInt32"
                ],
                [
                  "price_with_tax",
                  "UInt32"
                ],
                [
                  "price",
                  "UInt32"
                ]
              ],
              [
                2,
                165,
                150
              ],
              [
                3,
                220,
                200
              ]
            ]
          ]
        ]

- [select] `--slices[].post_filter` をサポートしました。

  - 以下のように、 `--slices[].filter` の条件でフィルターされた結果に対して `post_filter` を使えます。

        table_create Items TABLE_NO_KEY
        column_create Items price COLUMN_SCALAR UInt32

        load --table Items
        [
        {"price": 100},
        {"price": 200},
        {"price": 300},
        {"price": 1000},
        {"price": 2000},
        {"price": 3000}
        ]

        select Items \
          --slices[expensive].filter 'price >= 1000' \
          --slices[expensive].post_filter 'price < 3000'
        [
          [
            0,
            0.0,
            0.0
          ],
          [
            [
              [
                6
              ],
              [
                [
                  "_id",
                  "UInt32"
                ],
                [
                  "price",
                  "UInt32"
                ]
              ],
              [
                1,
                100
              ],
              [
                2,
                200
              ],
              [
                3,
                300
              ],
              [
                4,
                1000
              ],
              [
                5,
                2000
              ],
              [
                6,
                3000
              ]
            ],
            {
              "expensive": [
                [
                  2
                ],
                [
                  [
                    "_id",
                    "UInt32"
                  ],
                  [
                    "price",
                    "UInt32"
                  ]
                ],
                [
                  4,
                  1000
                ],
                [
                  5,
                  2000
                ]
              ]
            }
          ]
        ]

- [select] `--sort_keys` 内に式を記述できるようになりました。

  - `--sort_keys` に式を記述できます。

    - 存在しないキーが sort_keys の式に含まれていた場合、それらは、無視され警告がログに出力されます。

  - これによって、例えば、 `--sort_keys` に `VECTOR_COLUMN` の要素を指定し、 `VECTOR_COLUMN` の要素で結果をソートできます。

  - 以前のバージョンでも動的カラムを使えば、 `VECTOR COLUMN` の要素で結果をソートできましたが、この機能によって、動的カラムを使わずに `VECTOR_COLUMN` の要素で結果をソートできます。

        table_create Values TABLE_NO_KEY
        column_create Values numbers COLUMN_VECTOR Int32
        load --table Values
        [
        {"numbers": [127, 128, 129]},
        {"numbers": [126, 255]},
        {"numbers": [128, -254]}
        ]
        select Values --sort_keys 'numbers[1]' --output_columns numbers
        [
          [
            0,
            0.0,
            0.0
          ],
          [
            [
              [
                3
              ],
              [
                [
                  "numbers",
                  "Int32"
                ]
              ],
              [
                [
                  128,
                  -254
                ]
              ],
              [
                [
                  127,
                  128,
                  129
                ]
              ],
              [
                [
                  126,
                  255
                ]
              ]
            ]
          ]
        ]

- [トークンフィルター] オプションをつけた複数のトークンフィルターを使えるようにしました。

  - `--token_filters 'TokenFilterStopWord("column", "ignore"), TokenFilterNFKC130("unify_kana", true)'` のように複数のトークンフィルターを指定できます。 [Github#mroonga/mroonga#399][MASUDA Kazuhiroさんが報告]

- [query] 複雑な式で `result_set` ステージの動的カラムを扱えるようにしました。

  - 複雑な式とは、以下のように一時的な内部結果セットが必要な式です。

        '(true && query("name * 10", "ali", {"score_column": "ali_score"})) || \
         (true && query("name * 2", "li", {"score_column": "li_score"}))'

    - 上記の式では、 `true` の評価結果を格納するために一時的な結果セットを使用します。

    - したがって、例えば、以下の式では、式の中で `result_set` ステージの動的カラムの値を使えます。以下の式では、一時的な内部結果セットが必要ないためです。

          '(query("name * 10", "ali", {"score_column": "ali_score"})) || \
           (query("name * 2", "li", {"score_column": "li_score"}))'

  - 今回のリリースでは、以下のように `li_score` に値を設定できます。(以前のバージョンでは、2番めの式が動的カラムの値を取得出来なかったため、 `li_score` の値は `0` になっていました。)

        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 \
          --columns[ali_score].stage result_set \
          --columns[ali_score].type Float \
          --columns[ali_score].flags COLUMN_SCALAR \
          --columns[li_score].stage result_set \
          --columns[li_score].type Float \
          --columns[li_score].flags COLUMN_SCALAR \
          --output_columns name,_score,ali_score,li_score \
          --filter '(true && query("name * 10", "ali", {"score_column": "ali_score"})) || \
                    (true && query("name * 2", "li", {"score_column": "li_score"}))'
        [
          [
            0,
            0.0,
            0.0
          ],
          [
            [
              [
                2
              ],
              [
                [
                  "name",
                  "ShortText"
                ],
                [
                  "_score",
                  "Int32"
                ],
                [
                  "ali_score",
                  "Float"
                ],
                [
                  "li_score",
                  "Float"
                ]
              ],
              [
                "Alice",
                14,
                10.0,
                2.0
              ],
              [
                "Alisa",
                14,
                10.0,
                2.0
              ]
            ]
          ]
        ]

  - 以下のように、 `result_set` ステージの動的ベクターカラムも扱えるようにしました。

        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 \
          --columns[tags].stage result_set \
          --columns[tags].type ShortText \
          --columns[tags].flags COLUMN_VECTOR \
          --output_columns name,tags \
          --filter '(true && query("name", "al", {"tags": ["al"], "tags_column": "tags"})) || \
                    (true && query("name", "sa", {"tags": ["sa"], "tags_column": "tags"}))'
        [
          [
            0,
            0.0,
            0.0
          ],
          [
            [
              [
                2
              ],
              [
                [
                  "name",
                  "ShortText"
                ],
                [
                  "tags",
                  "ShortText"
                ]
              ],
              [
                "Alice",
                [
                  "al"
                ]
              ],
              [
                "Alisa",
                [
                  "al",
                  "sa"
                ]
              ]
            ]
          ]
        ]

    - 動的ベクターカラムを使う場合、格納する値は各要素が追加された値になります。

- [Ubuntu] Ubuntu 21.04 (Hirsute Hippo)をサポートしました。

- [httpd] バンドルしているnginxのバージョンを1.19.10に更新しました。

### 既知の問題

- 現在Groongaには、ベクターカラムに対してデータを大量に追加、削除、更新した際にデータが破損することがある問題があります。

- [ブラウザーベースの管理ツール] 現在Groongaには、レコード一覧の管理モードのチェックボックスにチェックを入れても、非管理モードに入力された検索クエリーが送信されるという問題があります。 [Github#1186][potiさんが報告]

### 感謝

- Anthony M. Cookさん

- MASUDA Kazuhiroさん

- potiさん

## 11.0.1リリース - 2021-03-31

### 改良

- [Debian GNU/Linux] ARM64向けのパッケージをサポートしました。

- [select] キーワードごとに重みをカスタマイズできるようにしました。

  - 今まで、スコアーを調整するには、すべてのキーワードに対して `<` や `>` を指定する必要がありました。デフォルトのスコアの重み(1)より、デフォルトの重みの調整量(6 または 4)のほうが大きいためです。

    - 例えば、`A <B` では、 "A" の重みは1、 "B" の重みは4になります。デクリメントされていない "A" の重み(1)より、デクリメントされた "B" の重み(4)のほうが大きくなります。これは、期待した動作ではありません。"B" に "A" より小さい重みを使うためには、 `>A <B` と指定する必要があります。`>A <B` では、 "A" の重みは6、 "B" の重みは4になります。

  - 今回のリリースから、対象のキーワードに `<${WEIGHT}` または `>${WEIGHT}` と指定するだけで、キーワードごとに重みの調整量をカスタマイズできます。例えば、 `A <0.1B` では、 "A" の重みは1、 "B" の重みは0.9になります。("B" の重みを0.1デクリメントしています。)

  - ただし、これらの形式(`>${WEIGHT}...`, `<${WEIGHT}...`, and `~${WEIGHT}...`)は互換性が無いことに注意してください。

- [select] Apache Arrow形式で `Float` と `Float32` の値を出力できるようにしました。

  - 例えば、以下のように出力します。

      table_create Data TABLE_NO_KEY
      column_create Data float COLUMN_SCALAR Float

      load --table Data
      [
      {"float": 1.1}
      ]

      select Data \
        --command_version 3 \
        --output_type apache-arrow

        return_code: int32
        start_time: timestamp[ns]
        elapsed_time: double
        -- metadata --
        GROONGA:data_type: metadata
         return_code                    start_time       elapsed_time
        0                  0     1970-01-01T09:00:00+09:00           0.000000
        ========================================
        _id: uint32
        float: double
        -- metadata --
        GROONGA:n_hits: 1
         _id          float
        0          1       1.100000

- [select] 結果出力時に、インデックスカラム経由で参照先のデータを取得できるようになりました。

  - 今までは、 出力値に `index_column.xxx` のように指定すると、Groongaは意図しない値を返していました。例えば以下の例では、 `--columns[tags].value purchases.tag` の値は、 `["apple",["many"]],["banana",["man"]],["cacao",["man"]]` になりました。このケースでは、期待される値は、 `["apple",["man","many"]],["banana",["man"]],["cacao",["woman"]]` でした。今回のリリースから、以下のように、インデックスカラム経由で参照先の正しい値を取得できます。

        table_create Products TABLE_PAT_KEY ShortText

        table_create Purchases TABLE_NO_KEY
        column_create Purchases product COLUMN_SCALAR Products
        column_create Purchases tag COLUMN_SCALAR ShortText

        column_create Products purchases COLUMN_INDEX Purchases product

        load --table Products
        [
        {"_key": "apple"},
        {"_key": "banana"},
        {"_key": "cacao"}
        ]

        load --table Purchases
        [
        {"product": "apple",  "tag": "man"},
        {"product": "banana", "tag": "man"},
        {"product": "cacao",  "tag": "woman"},
        {"product": "apple",  "tag": "many"}
        ]

        select Products \
          --columns[tags].stage output \
          --columns[tags].flags COLUMN_VECTOR \
          --columns[tags].type ShortText \
          --columns[tags].value purchases.tag \
          --output_columns _key,tags
        [
          [
            0,
            0.0,
            0.0
          ],
          [
            [
              [
                3
              ],
              [
                [
                  "_key",
                  "ShortText"
                ],
                [
                  "tags",
                  "ShortText"
                ]
              ],
              [
                "apple",
                [
                  "man",
                  "many"
                ]
              ],
              [
                "banana",
                [
                  "man"
                ]
              ],
              [
                "cacao",
                [
                  "woman"
                ]
              ]
            ]
          ]
        ]

- [select] ネストされたインデックスの一部として直接インデックスカラムを指定できるようになりました。

  - `index_column.except_source_column` を使ってフィルター後にソーステーブルを検索できます。例えば、以下の例では、検索時に `comments.content` を指定しています。この場合、最初に、このクエリは `Comments` テーブルの `content` カラムを全文検索し、次に `Comments` テーブルを検索した結果のレコードを参照する `Articles` テーブルのレコードを取得します。

        table_create Articles TABLE_HASH_KEY ShortText

        table_create Comments TABLE_NO_KEY
        column_create Comments article COLUMN_SCALAR Articles
        column_create Comments content COLUMN_SCALAR ShortText

        column_create Articles content COLUMN_SCALAR Text
        column_create Articles comments COLUMN_INDEX Comments article

        table_create Terms TABLE_PAT_KEY ShortText \
          --default_tokenizer TokenBigram \
          --normalizer NormalizerNFKC130
        column_create Terms articles_content COLUMN_INDEX|WITH_POSITION \
          Articles content
        column_create Terms comments_content COLUMN_INDEX|WITH_POSITION \
          Comments content

        load --table Articles
        [
        {"_key": "article-1", "content": "Groonga is fast!"},
        {"_key": "article-2", "content": "Groonga is useful!"},
        {"_key": "article-3", "content": "Mroonga is fast!"}
        ]

        load --table Comments
        [
        {"article": "article-1", "content": "I'm using Groonga too!"},
        {"article": "article-3", "content": "I'm using Mroonga!"},
        {"article": "article-1", "content": "I'm using PGroonga!"}
        ]

        select Articles --match_columns comments.content --query groonga \
          --output_columns "_key, _score, comments.content
        [
          [
            0,
            0.0,
            0.0
          ],
          [
            [
              [
                1
              ],
              [
                [
                  "_key",
                  "ShortText"
                ],
                [
                  "_score",
                  "Int32"
                ],
                [
                  "comments.content",
                  "ShortText"
                ]
              ],
              [
                "article-1",
                1,
                [
                  "I'm using Groonga too!",
                  "I'm using PGroonga!"
                ]
              ]
            ]
          ]
        ]

- [load] オブジェクトリテラルを使って、参照先のレコードをロードできるようにしました。

  - 例えば、以下のように、 `"key" : "[ { "key" : "value", ..., "key" : "value" } ]"` のようなデータをロードできます。

        table_create Purchases TABLE_NO_KEY
        column_create Purchases item COLUMN_SCALAR ShortText
        column_create Purchases price COLUMN_SCALAR UInt32

        table_create Settlements TABLE_HASH_KEY ShortText
        column_create Settlements purchases COLUMN_VECTOR Purchases
        column_create Purchases settlements_purchases COLUMN_INDEX Settlements purchases

        load --table Settlements
        [
        {
          "_key": "super market",
          "purchases": [
             {"item": "apple", "price": 100},
             {"item": "milk",  "price": 200}
          ]
        },
        {
          "_key": "shoes shop",
          "purchases": [
             {"item": "sneakers", "price": 3000}
          ]
        }
        ]

  - この機能によって、参照カラムにJSONデータを追加しやすくなります。

  - 現状、この機能は、JSONの入力のみをサポートしています。

- [load] JSON文字列で、参照先のレコードをロードできるようにしました。

  - 以下のように、JSONテキストを使ってソーステーブルから参照ベクターへデータをロードできます。

        table_create Purchases TABLE_HASH_KEY ShortText
        column_create Purchases item COLUMN_SCALAR ShortText
        column_create Purchases price COLUMN_SCALAR UInt32

        table_create Settlements TABLE_HASH_KEY ShortText
        column_create Settlements purchases COLUMN_VECTOR Purchases

        column_create Purchases settlements_purchases COLUMN_INDEX Settlements purchases

        load --table Settlements
        [
        {
          "_key": "super market",
          "purchases": "[{\"_key\": \"super market-1\", \"item\": \"apple\", \"price\": 100}, {\"_key\": \"super market-2\", \"item\": \"milk\",  \"price\": 200}]"
        },
        {
          "_key": "shoes shop",
          "purchases": "[{\"_key\": \"shoes shop-1\", \"item\": \"sneakers\", \"price\": 3000}]"
        }
        ]

        dump \
          --dump_plugins no \
          --dump_schema no
        load --table Purchases
        [
        ["_key","item","price"],
        ["super market-1","apple",100],
        ["super market-2","milk",200],
        ["shoes shop-1","sneakers",3000]
        ]

        load --table Settlements
        [
        ["_key","purchases"],
        ["super market",["super market-1","super market-2"]],
        ["shoes shop",["shoes shop-1"]]
        ]

        column_create Purchases settlements_purchases COLUMN_INDEX Settlements purchases

  - 現状、この機能は、ネストされた参照レコードをサポートしていません。

- [Windows] `time_classify_*` 関数で UNIXエポック を扱えるようになりました。

  - Groongaは、現地時刻でタイムスタンプを扱っています。したがって、例えば日本でUNIXエポックを入力した場合、入力した時刻はUNIXエポックの9時間前になります。

  - WindowsのAPIはUNIXエポックより前の時間が入力されるとエラーになります。

  - 今回のリリースから、以下のようにUNIXエポックを `time_classify_*` 内で使えるように

        plugin_register functions/time

        table_create Timestamps TABLE_PAT_KEY Time
        load --table Timestamps
        [
        {"_key": 0},
        {"_key": "2016-05-06 00:00:00.000001"},
        {"_key": "2016-05-06 23:59:59.999999"},
        {"_key": "2016-05-07 00:00:00.000000"},
        {"_key": "2016-05-07 00:00:00.000001"},
        {"_key": "2016-05-08 23:59:59.999999"},
        {"_key": "2016-05-08 00:00:00.000000"}
        ]

        select Timestamps \
          --sortby _id \
          --limit -1 \
          --output_columns '_key, time_classify_day_of_week(_key)'
        [
          [
            0,
            0.0,
            0.0
          ],
          [
            [
              [
                7
              ],
              [
                [
                  "_key",
                  "Time"
                ],
                [
                  "time_classify_day_of_week",
                  null
                ]
              ],
              [
                0.0,
                4
              ],
              [
                1462460400.000001,
                5
              ],
              [
                1462546799.999999,
                5
              ],
              [
                1462546800.0,
                6
              ],
              [
                1462546800.000001,
                6
              ],
              [
                1462719599.999999,
                0
              ],
              [
                1462633200.0,
                0
              ]
            ]
          ]
        ]

- [query_parallel_or] クエリーを並行して実行できる新しい関数を追加しました。

  - `query_parallel_or` でクエリーを並行で処理するためにはApache Arrowが必要です。Apache Arrowが無い場合は、 `query_parallel_or` はクエリーをシーケンシャルに実行します。

  - `query_parallel_or` は、 `match_columns` と `query_string` の組み合わせを平行に処理します。

  - `query_parallel_or` の構文は以下の通りです。:

        query_parallel_or(match_columns, query_string1,
                                         query_string2,
                                         .
                                         .
                                         .
                                         query_stringN,
                                         {"option": "value", ...})

- [select] 存在しないソートキーを無視するようにしました。

  - 今まで、存在しないソートキーを指定したとき、Groongaはエラーを出力していましたが、今回のリリースから存在しないソートキーを無視します。(エラーを出力しなくなります。)

  - この機能は、一貫性のために実装しています。`output_columns` も無効な値を無視します。また、 `sort_keys` も無効な値のほとんどを無視します。

- [select] drilldowns[].table で存在しないテーブルを無視します。 [GitHub#1169][naoaさんが報告]

  - 今まで、 `drilldowns[].table` で存在しないテーブルを指定したとき、Groongaはエラーを出力していましたが、今回のリリースから存在しないテーブルを無視します。(エラーを出力しなくなります。)

  - この機能は、一貫性のために実装しています。`output_columns` も無効な値を無視します。また、 `sort_keys` も無効な値のほとんどを無視します。

- [httpd] バンドルしているnginxのバージョンを1.19.8に更新しました。

### 修正

- [reference_acquire] 参照の自動リリースが発生する前に、テーブルにカラムが追加されテーブルの参照が獲得されたときにGroongaがクラッシュする問題を修正しました。

  - 追加されたカラムの参照は獲得されませんが、自動リリースの対象になるためです。

- [Windows] 別のスレッドで、他のバックトレースロギングプロセスが動作しているときに、新しくバックトレースロギングプロセスが開始されると、1つ以上のプロセスがSEGVのバックトレースの出力に失敗する問題を修正しました。

### 既知の問題

- 現在Groongaには、ベクターカラムに対してデータを大量に追加、削除、更新した際にデータが破損することがある問題があります。

### 感謝

- naoaさん

## 11.0.0リリース - 2021-02-09

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

### 改良

- [select] ネストされたインデックス経由でスカラーカラムとベクターカラムの値を出力できるようになりました。

  - ネストされたインデックスとは、以下のような構造です。

        table_create Products TABLE_PAT_KEY ShortText

        table_create Purchases TABLE_NO_KEY
        column_create Purchases product COLUMN_SCALAR Products
        column_create Purchases tag COLUMN_SCALAR ShortText

        column_create Products purchases COLUMN_INDEX Purchases product

  - 上記の例では、 `Products.purchases` カラムは `Purchases.product` カラムのインデックスです。また、 `Purchases.product` カラムは、 `Products` テーブルへの参照です。

  - 今までは、ネストされたインデックス経由の検索は、期待した結果を返しませんでした。

  - 今までの結果は以下のようになっていました。 `{"product": "apple", "tag": "man"}` が出力されていないことがわかります。

        table_create Products TABLE_PAT_KEY ShortText

        table_create Purchases TABLE_NO_KEY
        column_create Purchases product COLUMN_SCALAR Products
        column_create Purchases tag COLUMN_SCALAR ShortText

        column_create Products purchases COLUMN_INDEX Purchases product

        load --table Products
        [
        {"_key": "apple"},
        {"_key": "banana"},
        {"_key": "cacao"}
        ]

        load --table Purchases
        [
        {"product": "apple",  "tag": "man"},
        {"product": "banana", "tag": "man"},
        {"product": "cacao",  "tag": "woman"},
        {"product": "apple",  "tag": "many"}
        ]

        select Products \
          --output_columns _key,purchases.tag
        [
          [
            0,
            1612504193.380738,
            0.0002026557922363281
          ],
          [
            [
              [
                3
              ],
              [
                [
                  "_key",
                  "ShortText"
                ],
                [
                  "purchases.tag",
                  "ShortText"
                ]
              ],
              [
                "apple",
                "many"
              ],
              [
                "banana",
                "man"
              ],
              [
                "cacao",
                "man"
              ]
            ]
          ]
        ]

  - このリリースから、結果は以下のようになります。 `{"product": "apple", "tag": "man"}` が出力されているのがわかります。

        select Products \
          --output_columns _key,purchases.tag
        [
          [
            0,
            0.0,
            0.0
          ],
          [
            [
              [
                3
              ],
              [
                [
                  "_key",
                  "ShortText"
                ],
                [
                  "purchases.tags",
                  "Tags"
                ]
              ],
              [
                "apple",
                [
                  [
                    "man",
                    "one"
                  ],
                  [
                    "child",
                    "many"
                  ]
                ]
              ],
              [
                "banana",
                [
                  [
                    "man",
                    "many"
                  ]
                ]
              ],
              [
                "cacao",
                [
                  [
                    "woman"
                  ]
                ]
              ]
            ]
          ]
        ]

- [Windows] Linux上のMinGWを使ってクロスコンパイルしていたWindows向けパッケージの提供をやめました。

  - おそらく、ほとんどの人がこのパッケージを使っていないためです。

  - 上記のパッケージはこれまで、以下のような名前で提供されていたものです。

    - `groonga-x.x.x-x86.exe`

    - `groonga-x.x.x-x86.zip`

    - `groonga-x.x.x-x64.exe`

    - `groonga-x.x.x-x86.zip`

  - これからは、以下のパッケージを使用してください。

    - `groonga-latest-x86-vs2019-with-vcruntime.zip`

    - `groonga-latest-x64-vs2019-with-vcruntime.zip`

  - 既に Microsoft Visual C++ Runtime Library がインストール済みのシステムの場合は、以下のパッケージを使用してください。

    - `groonga-latest-x86-vs2019.zip`

    - `groonga-latest-x64-vs2019.zip`

### 修正

- インデックス内のデータを大量に追加、削除、更新した際にインデックスが破損することがある問題を修正しました。

  - この問題は、インデックス内のデータを大量に削除しただけでも発生します。ただ、インデックスにデータを追加しただけでは発生しません。

  - この問題によって破損したインデックスは、インデックスを再構築することで修復できます。

  - この問題は、壊れたインデックスを参照しない限り発覚しません。したがって、既にインデックスが破損しているかもしれません。

  - [index_column_diff] コマンドを使うことで、インデックスが破損しているかどうかを確認できます。

## 10.1.1リリース - 2021-01-25

### 改良

- [select] Apache Arrow形式でUInt64の値の出力をサポートしました。

- [select] Apache Arrow形式で以下のようにヒット数の出力をサポートしました。

      -- metadata --
      GROONGA:n-hits: 10

- [query] "order by estimated size" の最適化をサポートしました。

  - 通常、ヒット数の少ない条件から最初に実行すると、高速に検索できます。

    - "A (ヒット数が多い) && B (ヒット数が少ない)" より "B (ヒット数が少ない) && A (ヒット数が多い)" 方が高速です。

  - これは、よく知られた最適化ですが、自分で条件を並び替える必要があります。

  - Groongaは、 "order by estimated size" の最適化を使うことで、自動的にこの並び替えを実行します。

  - この最適化は、 `GRN_ORDER_BY_ESTIMATED_SIZE_ENABLE=yes` で有効になります。

- [between] 以下の改良で、パフォーマンスを改善しました。

  - `between()` でシーケンシャルサーチを使うかどうかの判断の精度を改善しました。

  - `between()` の結果を結果セットに一度にセットするよう改善しました。

- [select] 前方一致検索のパフォーマンスを改善しました。

  - 例えば、以下のような "*" を使った前方一致検索のパフォーマンスが向上します。

        table_create Memos TABLE_PAT_KEY ShortText
        table_create Contents TABLE_PAT_KEY ShortText   --normalizer NormalizerAuto
        column_create Contents entries_key_index COLUMN_INDEX Memos _key

        load --table Memos
        [
        {"_key": "(groonga) Start to try!"},
        {"_key": "(mroonga) Installed"},
        {"_key": "(groonga) Upgraded!"}
        ]

        select \
          --table Memos \
          --match_columns _key \
          --query '\\(groonga\\)*'

- [トークナイザー][TokenMecab] トークンカラムを並列で構築する際のパフォーマンスを改善しました。 [GitHub#1158][naoaさんがパッチ提供]

### 修正

- [sub_filter] `slices[].filter` 内で `sub_filter` が動作しない問題を修正しました。

  - 例えば、以下のクエリーでは、この問題によって、 `sub_filter` の結果は0件になります。

        table_create Users TABLE_HASH_KEY ShortText
        column_create Users age COLUMN_SCALAR UInt8

        table_create Memos TABLE_NO_KEY
        column_create Memos user COLUMN_SCALAR Users
        column_create Memos content COLUMN_SCALAR Text

        load --table Users
        [
        {"_key": "alice", "age": 9},
        {"_key": "bob",   "age": 29}
        ]

        load --table Memos
        [
        {"user": "alice", "content": "hello"},
        {"user": "bob",   "content": "world"},
        {"user": "alice", "content": "bye"},
        {"user": "bob",   "content": "yay"}
        ]

        select \
          --table Memos \
          --slices[adult].filter '_id > 1 && sub_filter(user, "age >= 18")'

- ハッシュテーブルに対して、繰り返し大量のデータを追加、削除すると、Groongaがクラッシュしたり、データの追加ができなくなる可能性がある問題を修正しました。

### 感謝

- naoaさん

## 10.1.0リリース - 2020-12-29

### 改良

- [highlight_html] 全角スペースをハイライト対処から除外しました。[PGroonga#GitHub#155][Hung Nguyen Vさんが報告]

  - 今までは、以下のように先頭の全角スペースも含めてハイライト対象としていました。

        table_create Entries TABLE_NO_KEY
        column_create Entries body COLUMN_SCALAR ShortText

        table_create Terms TABLE_PAT_KEY ShortText --default_tokenizer TokenBigram --normalizer NormalizerAuto
        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)'
        [
          [
            0,
            0.0,
            0.0
          ],
          [
            [
              [
                1
              ],
              [
                [
                  "highlight_html",
                  null
                ]
              ],
              [
                "Groonga<span class=\"keyword\">　高速</span>！"
              ]
            ]
          ]
        ]

  - しかし、この全角スペースはハイライト対象としては不要です。そのため、このリリースから `highlight_html()` は先頭の全角スペースを削除します。

- [status] 新しい項目 `features` を追加しました。

  - 以下のように、Groongaのどの機能が有効なのかを表示できます。

        status --output_pretty yes
        [
          [
            0,
            0.0,
            0.0
          ],
          {
            "alloc_count": 361,
            "starttime": 1608087311,
            "start_time": 1608087311,
            "uptime": 35,
            "version": "10.1.0",
            "n_queries": 0,
            "cache_hit_rate": 0.0,
            "command_version": 1,
            "default_command_version": 1,
            "max_command_version": 3,
            "n_jobs": 0,
            "features": {
              "nfkc": true,
              "mecab": true,
              "message_pack": true,
              "mruby": true,
              "onigmo": true,
              "zlib": true,
              "lz4": false,
              "zstandard": false,
              "kqueue": false,
              "epoll": true,
              "poll": false,
              "rapidjson": false,
              "apache_arrow": false,
              "xxhash": false
            }
          }
        ]

- [status] 新しい項目 `apache_arrow` を追加しました。

  - 以下のようにGroongaが使うApache Arrowのバージョンを表示できます。

      [
        [
          0,
          1608088628.440753,
          0.0006628036499023438
        ],
        {
          "alloc_count": 360,
          "starttime": 1608088617,
          "start_time": 1608088617,
          "uptime": 11,
          "version": "10.0.9-39-g5a4c6f3",
          "n_queries": 0,
          "cache_hit_rate": 0.0,
          "command_version": 1,
          "default_command_version": 1,
          "max_command_version": 3,
          "n_jobs": 0,
          "features": {
            "nfkc": true,
            "mecab": true,
            "message_pack": true,
            "mruby": true,
            "onigmo": true,
            "zlib": true,
            "lz4": true,
            "zstandard": false,
            "kqueue": false,
            "epoll": true,
            "poll": false,
            "rapidjson": false,
            "apache_arrow": true,
            "xxhash": false
          },
          "apache_arrow": {
            "version_major": 2,
            "version_minor": 0,
            "version_patch": 0,
            "version": "2.0.0"
          }
        }
      ]

  - この項目は、Apache Arrowが有効な場合にのみ表示されます。

- [ウィンドウ関数] 対象のテーブルがシャードをまたいでいる場合でも、全てのテーブルを一度に処理するようにしました。(実験的)

  - 今まで、対象のテーブルがシャードをまたいでいた場合、ウインドウ関数はシャード毎に処理をしていました。

    - そのため、複数のグループキーを使う場合、2番目以降のグループキーの値は1種類でなければなりませんでした。

    - この改良によって、以下のように複数の種類の値を2番目以降のグループキーで使用できるようになります。

          plugin_register sharding
          plugin_register functions/time

          table_create Logs_20170315 TABLE_NO_KEY
          column_create Logs_20170315 timestamp COLUMN_SCALAR Time
          column_create Logs_20170315 price COLUMN_SCALAR UInt32
          column_create Logs_20170315 item COLUMN_SCALAR ShortText

          table_create Logs_20170316 TABLE_NO_KEY
          column_create Logs_20170316 timestamp COLUMN_SCALAR Time
          column_create Logs_20170316 price COLUMN_SCALAR UInt32
          column_create Logs_20170316 item COLUMN_SCALAR ShortText

          table_create Logs_20170317 TABLE_NO_KEY
          column_create Logs_20170317 timestamp COLUMN_SCALAR Time
          column_create Logs_20170317 price COLUMN_SCALAR UInt32
          column_create Logs_20170317 item COLUMN_SCALAR ShortText

          load --table Logs_20170315
          [
          {"timestamp": "2017/03/15 10:00:00", "price": 1000, "item": "A"},
          {"timestamp": "2017/03/15 11:00:00", "price":  900, "item": "A"},
          {"timestamp": "2017/03/15 12:00:00", "price":  300, "item": "B"},
          {"timestamp": "2017/03/15 13:00:00", "price":  200, "item": "B"}
          ]

          load --table Logs_20170316
          [
          {"timestamp": "2017/03/16 10:00:00", "price":  530, "item": "A"},
          {"timestamp": "2017/03/16 11:00:00", "price":  520, "item": "B"},
          {"timestamp": "2017/03/16 12:00:00", "price":  110, "item": "A"},
          {"timestamp": "2017/03/16 13:00:00", "price":  410, "item": "A"},
          {"timestamp": "2017/03/16 14:00:00", "price":  710, "item": "B"}
          ]

          load --table Logs_20170317
          [
          {"timestamp": "2017/03/17 10:00:00", "price":  800, "item": "A"},
          {"timestamp": "2017/03/17 11:00:00", "price":  400, "item": "B"},
          {"timestamp": "2017/03/17 12:00:00", "price":  500, "item": "B"},
          {"timestamp": "2017/03/17 13:00:00", "price":  300, "item": "A"}
          ]

          table_create Times TABLE_PAT_KEY Time
          column_create Times logs_20170315 COLUMN_INDEX Logs_20170315 timestamp
          column_create Times logs_20170316 COLUMN_INDEX Logs_20170316 timestamp
          column_create Times logs_20170317 COLUMN_INDEX Logs_20170317 timestamp

          logical_range_filter Logs \
            --shard_key timestamp \
            --filter 'price >= 300' \
            --limit -1 \
            --columns[offsetted_timestamp].stage filtered \
            --columns[offsetted_timestamp].type Time \
            --columns[offsetted_timestamp].flags COLUMN_SCALAR \
            --columns[offsetted_timestamp].value 'timestamp - 39600000000' \
            --columns[offsetted_day].stage filtered \
            --columns[offsetted_day].type Time \
            --columns[offsetted_day].flags COLUMN_SCALAR \
            --columns[offsetted_day].value 'time_classify_day(offsetted_timestamp)' \
            --columns[n_records_per_day_and_item].stage filtered \
            --columns[n_records_per_day_and_item].type UInt32 \
            --columns[n_records_per_day_and_item].flags COLUMN_SCALAR \
            --columns[n_records_per_day_and_item].value 'window_count()' \
            --columns[n_records_per_day_and_item].window.group_keys 'offsetted_day,item' \
            --output_columns "_id,time_format_iso8601(offsetted_day),item,n_records_per_day_and_item"
          [
            [
              0,
              0.0,
              0.0
            ],
            [
              [
                [
                  "_id",
                  "UInt32"
                ],
                [
                  "time_format_iso8601",
                  null
                ],
                [
                  "item",
                  "ShortText"
                ],
                [
                  "n_records_per_day_and_item",
                  "UInt32"
                ]
              ],
              [
                1,
                "2017-03-14T00:00:00.000000+09:00",
                "A",
                1
              ],
              [
                2,
                "2017-03-15T00:00:00.000000+09:00",
                "A",
                2
              ],
              [
                3,
                "2017-03-15T00:00:00.000000+09:00",
                "B",
                1
              ],
              [
                1,
                "2017-03-15T00:00:00.000000+09:00",
                "A",
                2
              ],
              [
                2,
                "2017-03-16T00:00:00.000000+09:00",
                "B",
                2
              ],
              [
                4,
                "2017-03-16T00:00:00.000000+09:00",
                "A",
                2
              ],
              [
                5,
                "2017-03-16T00:00:00.000000+09:00",
                "B",
                2
              ],
              [
                1,
                "2017-03-16T00:00:00.000000+09:00",
                "A",
                2
              ],
              [
                2,
                "2017-03-17T00:00:00.000000+09:00",
                "B",
                2
              ],
              [
                3,
                "2017-03-17T00:00:00.000000+09:00",
                "B",
                2
              ],
              [
                4,
                "2017-03-17T00:00:00.000000+09:00",
                "A",
                1
              ]
            ]
          ]

  - この機能には、まだリリースされていない、Apache Arrow 3.0.0が必要です。

- 参照カラムに対する検索でシーケンシャルサーチをサポートしました。

  - この機能は、インデックス検索でたくさんのレコードがマッチした場合、かつ結果セットが十分小さい場合にのみ使われます。

    - 上記のケースでは、インデックス検索よりもシーケンシャルサーチの方が速いためです。

  - この機能はデフォルトでは無効です。

  - この機能は、環境変数 `GRN_II_SELECT_TOO_MANY_INDEX_MATCH_RATIO_REFERENCE` を設定することで有効になります。

  - 環境変数 `GRN_II_SELECT_TOO_MANY_INDEX_MATCH_RATIO_REFERENCE` はインデックス検索からシーケンシャルサーチに切り替えるためのしきい値です。

    - 例えば、以下のように `GRN_II_SELECT_TOO_MANY_INDEX_MATCH_RATIO_REFERENCE=0.7` とセットした場合、結果セットのレコード数が、総レコード数の70%以下の場合にシーケンシャルサーチで検索します。

          $ export GRN_II_SELECT_TOO_MANY_INDEX_MATCH_RATIO_REFERENCE=0.7

          table_create Tags TABLE_HASH_KEY ShortText
          table_create Memos TABLE_HASH_KEY ShortText
          column_create Memos tag COLUMN_SCALAR Tags

          load --table Memos
          [
          {"_key": "Rroonga is fast!", "tag": "Rroonga"},
          {"_key": "Groonga is fast!", "tag": "Groonga"},
          {"_key": "Mroonga is fast!", "tag": "Mroonga"},
          {"_key": "Groonga sticker!", "tag": "Groonga"},
          {"_key": "Groonga is good!", "tag": "Groonga"}
          ]

          column_create Tags memos_tag COLUMN_INDEX Memos tag

          select Memos --query '_id:>=3 tag:@Groonga' --output_columns _id,_score,_key,tag
          [
            [
              0,
              0.0,
              0.0
            ],
            [
              [
                [
                  2
                ],
                [
                  [
                    "_id",
                    "UInt32"
                  ],
                  [
                    "_score",
                    "Int32"
                  ],
                  [
                    "_key",
                    "ShortText"
                  ],
                  [
                    "tag",
                    "Tags"
                  ]
                ],
                [
                  4,
                  2,
                  "Groonga sticker!",
                  "Groonga"
                ],
                [
                  5,
                  2,
                  "Groonga is good!",
                  "Groonga"
                ]
              ]
            ]
          ]

- [tokenizers] `TokenDocumentVectorTFIDF` と `TokenDocumentVectorBM25` でトークンカラムをサポートしました。

  - インデックスカラムと同じソースを持つトークンカラムがある場合、これらのトークナイザーは、トークンカラムのトークンIDを使います。

    - トークンカラムは、既にトークナイズ済みのデータを持っています。

    - そのため、トークンカラムを使うことによって、これらのトークナイザーのパフォーマンスが改善されます。

  - 例えば、以下のように、 `content_tokens` というトークンカラムを作ることで、この機能を使えます。

        table_create Memos TABLE_NO_KEY
        column_create Memos content COLUMN_SCALAR Text

        load --table Memos
        [
        {"content": "a b c a"},
        {"content": "c b c"},
        {"content": "b b a"},
        {"content": "a c c"},
        {"content": "a"}
        ]

        table_create Tokens TABLE_PAT_KEY ShortText \
          --normalizer NormalizerNFKC121 \
          --default_tokenizer TokenNgram
        column_create Tokens memos_content COLUMN_INDEX|WITH_POSITION Memos content

        column_create Memos content_tokens COLUMN_VECTOR Tokens content

        table_create DocumentVectorBM25 TABLE_HASH_KEY Tokens \
          --default_tokenizer \
            'TokenDocumentVectorBM25("index_column", "memos_content", \
                                     "df_column", "df")'
        column_create DocumentVectorBM25 df COLUMN_SCALAR UInt32

        column_create Memos content_feature COLUMN_VECTOR|WITH_WEIGHT|WEIGHT_FLOAT32 \
          DocumentVectorBM25 content

        select Memos
        [
          [
            0,
            0.0,
            0.0
          ],
          [
            [
              [
                5
              ],
              [
                [
                  "_id",
                  "UInt32"
                ],
                [
                  "content",
                  "Text"
                ],
                [
                  "content_feature",
                  "DocumentVectorBM25"
                ],
                [
                  "content_tokens",
                  "Tokens"
                ]
              ],
              [
                1,
                "a b c a",
                {
                  "a": 0.5095787,
                  "b": 0.6084117,
                  "c": 0.6084117
                },
                [
                  "a",
                  "b",
                  "c",
                  "a"
                ]
              ],
              [
                2,
                "c b c",
                {
                  "c": 0.8342565,
                  "b": 0.5513765
                },
                [
                  "c",
                  "b",
                  "c"
                ]
              ],
              [
                3,
                "b b a",
                {
                  "b": 0.9430448,
                  "a": 0.3326656
                },
                [
                  "b",
                  "b",
                  "a"
                ]
              ],
              [
                4,
                "a c c",
                {
                  "a": 0.3326656,
                  "c": 0.9430448
                },
                [
                  "a",
                  "c",
                  "c"
                ]
              ],
              [
                5,
                "a",
                {
                  "a": 1.0
                },
                [
                  "a"
                ]
              ]
            ]
          ]
        ]

  - `TokenDocumentVectorTFIDF` と `TokenDocumentVectorBM25` は、各トークンに対して重みをつけます。

    - `TokenDocumentVectorTFIDF` は、TF-IDFを使ってトークンの重みを計算します。

      > - TF-IDFについては、 https://radimrehurek.com/gensim/models/tfidfmodel.html を参照してください。

    - `TokenDocumentVectorBM25` は、Okapi BM25を使ってトークンの重みを計算します。

      > - Okapi BM25については、 https://en.wikipedia.org/wiki/Okapi_BM25 を参照してください。

- 以下のケースのパフォーマンスを改善しました。

  - `(column @ "value") && (column @ "value")`

- [Ubuntu] Ubuntu 20.10 (Groovy Gorilla)をサポートしました。

- [Debian GNU/Linux] stretchのサポートをやめました。

  - EOLになったためです。

- [CentOS] CentOS 6のサポートをやめました。

  - EOLになったためです。

- [httpd] バンドルしているnginxのバージョンを1.19.6に更新しました。

### 修正

- 以下のように、複数のドリルダウンのキーと複数のアクセサーを使用した時にGroongaがクラッシュする問題を修正しました。[GitHub#1153][naoaさんがパッチ提供]

      table_create Tags TABLE_PAT_KEY ShortText

      table_create Memos TABLE_HASH_KEY ShortText
      column_create Memos tags COLUMN_VECTOR Tags
      column_create Memos year COLUMN_SCALAR Int32

      load --table Memos
      [
      {"_key": "Groonga is fast!", "tags": ["full-text-search"], "year": 2019},
      {"_key": "Mroonga is fast!", "tags": ["mysql", "full-text-search"], "year": 2019},
      {"_key": "Groonga sticker!", "tags": ["full-text-search", "sticker"], "year": 2020},
      {"_key": "Rroonga is fast!", "tags": ["full-text-search", "ruby"], "year": 2020},
      {"_key": "Groonga is good!", "tags": ["full-text-search"], "year": 2020}
      ]

      select Memos \
        --filter '_id > 0' \
        --drilldowns[tags].keys 'tags,year >= 2020' \
        --drilldowns[tags].output_columns _key[0],_key[1],_nsubrecs

      select Memos \
        --filter '_id > 0' \
        --drilldowns[tags].keys 'tags,year >= 2020' \
        --drilldowns[tags].output_columns _key[1],_nsubrecs

- 以下のように、同じフレーズが複数回出現すると、近傍フレーズ検索がマッチしない問題を修正しました。

      table_create Entries TABLE_NO_KEY
      column_create Entries content COLUMN_SCALAR Text

      table_create Terms TABLE_PAT_KEY ShortText \
        --default_tokenizer TokenNgram \
        --normalizer NormalizerNFKC121
      column_create Terms entries_content COLUMN_INDEX|WITH_POSITION Entries content

      load --table Entries
      [
      {"content": "a x a x b x x"},
      {"content": "a x x b x"}
      ]

      select Entries \
        --match_columns content \
        --query '*NP2"a b"' \
        --output_columns '_score, content'

### 感謝

- Hung Nguyen Vさん

- naoaさん

- timgates42さん [GitHub#1155にてパッチ提供]

## 10.0.9リリース - 2020-12-01

### 改良

- `limit` に `-1` を指定した時のパフォーマンスを改善しました。

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

  - Groongaは、リクエストが `--auto_release_count` で指定された値に到達した時に自動的に参照カウントを減らします。

  - 例えば、以下のように、取得した `User` の参照は、2番目の `status` が処理された後に自動的に解放されます。

        reference_acquire --target_name Users --auto_release_count 2
        status # Users is still referred.
        status # Users' reference is released after this command is processed.

  - このオプションで、取得した参照の解放漏れを防げます。

- Groongaが空の `vector` や `uvector` を評価した時の動作を変更しました。

  - 空の `vector` と `uvector` はcommand version 3では、 `false` と評価されます。

    - この挙動はcommand version 3でのみ有効です。

    - 今までとは挙動が異なることに注意してください。

- [ノーマライザー] Unicode 13.0 の NFKC（Normalization Form Compatibility Composition）をベースにしたノーマライザー `NormalizerNFKC130` を追加しました。

- [トークンフィルター] Unicode 13.0 の NFKC（Normalization Form Compatibility Composition）をベースにしたトークンフィルター `TokenFilterNFKC130` を追加しました。

- [select] `"_score = column - X"` のパフォーマンスを改善しました。

- [reference_acquire] `--recursive dependent` オプションを指定した時に必要のないインデックスカラムへの参照を取得しないように改善しました。

  - 今回のリリースから、 `--recursive dependent` の対象は、対象のテーブルのキーあるいはデータカラムに設定してあるインデックスカラムです。

- [select] 順序限定の近傍フレーズ検索をサポートしました。

  - 今までの近傍フレーズ検索は、指定したフレーズ間の距離が近いレコードのみを探していました。

  - この機能は、以下の条件を満たすレコードを探します。

    - 指定したフレーズ間の距離が近い場合。

    - 指定したフレーズが指定した順序で並んでいる場合。

  - この機能は、 `*ONP` を演算子として使います。(`*NP` 演算子ではないことに注意してください。)

  - `$` はクエリー構文では、 `$` そのものとして扱います。クエリー構文では、 `$` は特殊文字ではないことに注意してください。

  - スクリプト構文の場合、この機能は以下のように使用します。

        table_create Entries TABLE_NO_KEY
        column_create Entries content COLUMN_SCALAR Text

        table_create Terms TABLE_PAT_KEY ShortText \
          --default_tokenizer 'TokenNgram("unify_alphabet", false, \
                                          "unify_digit", false)' \
          --normalizer NormalizerNFKC121
        column_create Terms entries_content COLUMN_INDEX|WITH_POSITION Entries content

        load --table Entries
        [
        {"content": "abcXYZdef"},
        {"content": "abebcdXYZdef"},
        {"content": "abcdef"},
        {"content": "defXYZabc"},
        {"content": "XYZabc"},
        {"content": "abc123456789def"},
        {"content": "abc12345678def"},
        {"content": "abc1de2def"}
        ]

        select Entries --filter 'content *ONP "abc def"' --output_columns '_score, content'
        [
          [
            0,
            0.0,
            0.0
          ],
          [
            [
              [
                4
              ],
              [
                [
                  "_score",
                  "Int32"
                ],
                [
                  "content",
                  "Text"
                ]
              ],
              [
                1,
                "abcXYZdef"
              ],
              [
                1,
                "abcdef"
              ],
              [
                1,
                "abc12345678def"
              ],
              [
                1,
                "abc1de2def"
              ]
            ]
          ]
        ]

  - クエリー構文の場合、この機能は以下のように使用します。

        select Entries --query 'content:*ONP "abc def"' --output_columns '_score, content'
        [
          [
            0,
            0.0,
            0.0
          ],
          [
            [
              [
                4
              ],
              [
                [
                  "_score",
                  "Int32"
                ],
                [
                  "content",
                  "Text"
                ]
              ],
              [
                1,
                "abcXYZdef"
              ],
              [
                1,
                "abcdef"
              ],
              [
                1,
                "abc12345678def"
              ],
              [
                1,
                "abc1de2def"
              ]
            ]
          ]
        ]

- [httpd] バンドルしているnginxのバージョンを1.19.5に更新しました。

### 修正

- [Groonga HTTPサーバー] Groonga HTTP server が全てのワーカースレッドの完全な終了を待たずに終了していた問題を修正しました。

  - 今まで、Groonga HTTP server は、ワーカースレッドの処理が終了した後から、自身の終了処理を開始していました。しかし、このタイミングでは、ワーカースレッドは完全に終了していないことがあります。そのため、タイミングによってはGroonga HTTP serverがクラッシュすることがあります。Groonga HTTP server がワーカースレッドがまだ使用している領域を解放することがあるためです。

## 10.0.8リリース - 2020-10-29

### 改良

- [select] 大きいサイズのドリルダウンのキーを使えるようになりました。

  - Groongaのテーブルのキーサイズの最大は4KiBですが、複数のドリルダウンのキーを指定している場合、ドリルダウンのキーのサイズが4KiBを超える場合があります。

    - 例えば、以下のケースで、 `tag` キーと `n_like` キーのトータルサイズが4KiB以上だった場合、ドリルダウンは失敗します。

        select Entries \
          --limit -1 \
          --output_columns tag,n_likes \
          --drilldowns[tag.n_likes].keys tag,n_likes \
          --drilldowns[tag.n_likes].output_columns _value.tag,_value.n_likes,_nsubrecs

    - ドリルダウンは指定されている全てのキーを連結しているためです。そのため、ドリルダウンのキーそれぞれが大きい場合は、ドリルダウンのキーを連結したサイズが4KiB以上になります。

  - この機能には、 xxHash が必要です。

    - ただ、Groongaをパッケージからインストールしている場合は、特に何もしなくてもこの機能を使えます。Groongaのパッケージには、すでに xxHash が含まれているためです。

- [select] 異なるテーブルを参照しているカラムを同じ動的カラムで扱えるようにしました。

  - 従来、異なるテーブルを参照しているカラムは、同一の動的カラムでは扱えませんでした。カラムの型が異なるためです。

  - 今回のバージョンから、以下のように異なるテーブルを参照しているカラムであってもビルトインの型にキャストすることで同じ動的カラムで扱うことができます。

        table_create Store_A TABLE_HASH_KEY ShortText
        table_create Store_B TABLE_HASH_KEY ShortText

        table_create Customers TABLE_HASH_KEY Int32
        column_create Customers customers_A COLUMN_VECTOR Store_A
        column_create Customers customers_B COLUMN_VECTOR Store_B

        load --table Customers
        [
          {"_key": 1604020694, "customers_A": ["A", "B", "C"]},
          {"_key": 1602724694, "customers_B": ["Z", "V", "Y", "T"]},
        ]

        select Customers \
          --filter '_key == 1604020694' \
          --columns[customers].stage output \
          --columns[customers].flags COLUMN_VECTOR \
          --columns[customers].type ShortText \
          --columns[customers].value 'customers_A' \
          --output_columns '_key, customers'

  - 今までは、 `Store_A` または `Store_B` を `customers` カラムの`type`に設定する必要がありました。

  - 上記の例では、 `customers_A` カラムの型は、 `ShortText` にキャストします。

  - `customers_A` のキーも `customers_B` のキーも `ShortText` 型であるため、これで `customers` カラムの値に `customers_B` の値も設定できます。

- [select] 検索結果のレコード数が非常に多い場合のパフォーマンスを改善しました。

  - この最適化は、以下のケースで効果があります。

    - `--filter 'column <= "value"'` or `--filter 'column >= "value"'`

    - `--filter 'column == "value"'`

    - `--filter 'between(...)'` または `--filter 'between(_key, ...)'`

    - `--filter 'sub_filter(reference_column, ...)'`

    - `--filter '_key > "value"'` のような `_key` に対する比較

    - `--filter 'geo_in_circle(...)'`

- バンドルしているLZ4を1.8.2から1.9.2に更新しました。

- xxHash 0.8 をサポートしました。

- [httpd] バンドルしているnginxのバージョンを1.19.4に更新しました。

### 修正

- ブラウザーベースの管理ツール関連の問題を修正しました。　[GitHub#1139][sutaminさんの報告]

  - Groongaのロゴが表示されない問題。

  - 日本語のインデックスページにスループットグラフが表示されない問題。

- [between] `between(_key, ...)` が常にシーケンシャルサーチで評価される問題を修正しました。

### 感謝

- sutaminさん

## 10.0.7リリース - 2020-09-29

### 改良

- [highlight], [highlight_full] ノーマライザーにオプションを指定できるようになりました。

- [リターンコード] 新しいリターンコード `GRN_CONNECTION_RESET` を追加しました。

  - このリターンコードは、リモートホストから強制的に接続を切断されたときに返されます。

- Ubuntu 19.10(Eoan Ermine)のサポートをやめました。

  - このバージョンはEOLになっているためです。

- [httpd] バンドルしているnginxのバージョンを1.19.2に更新しました。

- [grndb] キーの重複を検出できるようになりました。

  - 今回のリリースから、`grndb check` でキーの重複も検出できるようになりました。

  - このチェックは、 `TABLE_NO_KEY` のテーブル以外で有効です。

  - `grndb check` で重複が検出されたテーブルにインデックスカラムしかない場合は、 `grndb recover` で復旧できます。

- [table_create], [column_create] 新しいオプション `--path` を追加しました。

  - このオプションによって指定したテーブルまたは、カラムを任意のパスに格納できます。

  - このオプションは、高速なストレージ(SSDなど)によく使うテーブルやカラムを格納し、低速なストレージ(HDDなど)にあまり使わないテーブルやカラムを格納したいときに有用です。

  - このオプションは、相対パス、絶対パスの両方が指定できます。

    - 相対パスを指定した場合は、 `groonga` プロセスのパスを起点に指定したパスが解決されます。

  - `--path` を指定した場合、 `dump` コマンドの結果に `--path` の情報が含まれます。

    - したがって、 `--path` を指定した場合、 異なる環境のホストではリストアできなくなります。

      - これは、ディレクトリ構成や `groonga` プロセスの場所が環境ごとに異なるためです。

    - `--path` の情報を `dump` に含みたくない場合は、 `dump` コマンド実行時に `--dump_paths no` を指定する必要があります。

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

  - `--dump_paths` オプションは、 `--path` をダンプするかどうかを制御します。

  - デフォルト値は `yes` です。

  - もし、テーブルやカラム作成時に `--path` を指定していて、 `--path` の情報を `dump` に含みたくない場合は、 `dump` コマンド実行時に `--dump_paths` に `no` を指定してください。

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

  - この関数は、第二引数に指定されたカラムの値を、第一引数に指定されたトークナイザーでトークナイズします。

- [tokenizers] 新しいトークナイザー `TokenDocumentVectorTFIDF` を追加しました。(実験的)

  - このトークナイザーは、TF-IDFで文書ベクトルを自動で生成します。

- [tokenizers] 新しいトークナイザー `TokenDocumentVectorBM25` を追加しました。(実験的)

  - このトークナイザーは、BM25で文書ベクトルを自動で生成します。

- [select] 同一センテンス内での、フレーズ近傍検索をサポートしました。

### 修正

- [load] 257個のカラムに対して `load` を実行すると `load` の応答が返らなくなる問題を修正しました。

  - この問題は、10.0.4以降で発生する可能性があります。

  - この問題は、 `[a, b, c, ...]` の形式でデータをロードした時にのみ発生します。

    - `[{...}]` を使ってデータをロードした場合は発生しません。

- [MessagePack] float32の値を正しくアンパックできない問題を修正しました。

- マルチカラムインデックス関連の問題を修正しました。

  - `_score` の値が壊れることがあります。

  - ヒットしないはずのレコードがヒットすることがあります。

  - この問題の発生条件については、以下のURLを参照してください。

    - https://groonga.org/ja/blog/2020/09/29/groonga-10.0.7.html#multi-column-index

## 10.0.6リリース - 2020-08-29

### 改良

- [logical_range_filter] 大きなデータの検索プランを改善しました。

  - 通常、 `logical_range_filter` は `logical_select` より高速ですが、以下のケースでは、 `logical_select` より遅くなっていました。

    - `logical_range_filter` には要求されたレコード数をなかなか見つけられない場合にシーケンシャル検索からインデックス検索に切り替える機能があります。( `logical_range_filter` は通常、検索対象のレコード数が多い場合は、シーケンシャル検索を使います。)

    - 上記の切り替えが発生した場合は、 `logical_select` と検索処理がほぼ同じになります。そのため、大きなデータを対象とした検索では、上記のケースで、 `logical_range_filter` は、 `logical_select` の数倍遅くなります。なぜなら、 `logical_range_filter` は検索後にソートを実行するためです。

  - 今回のリリースから、大きなデータを検索する場合に、今までよりシーケンシャル検索が採用されやすくしました。

  - これによって、 `logical_select` と同等の処理になるケースが減少し `logical_range_filter` のパフォーマンスが改善します。

- [httpd] バンドルしているnginxのバージョンを1.19.1に更新しました。

- Debian GNU/Linux へのインストール方法を変更しました。

  - `groonga-archive-keyring` の代わりに `groonga-apt-source` を使うように変更しました。 `lintian` コマンドが `/etc/apt/sources.lists.d/` 配下にファイルを置くパッケージは `apt-source` を使うよう推奨しているためです。

    - `lintian` コマンドはパッケージングに共通のエラーをチェックするためのコマンドです。

    - インストール方法についての詳細は、以下のURLも参照してください。

      - https://groonga.org/ja/docs/install/debian.html

- [logical_select] `highlight_html` と `highlight_full` をサポートしました。

- 値を持たない配列を削除した時、そのレコードのIDを再利用するようにしました。[GitHub#mroonga/mroonga#327][gaeeyoさんの報告]

  - 値を持たない配列を削除した場合、削除されたIDは再利用されません。

  - Groongaは大きなIDがあることによって、多くのストレージを使用します。大きなIDはそれだけで、多くのストレージを使うためです。

    - 大きなIDは、例えば、Mroongaの `mroonga_operations` のように多くの追加と削除によって発生します。

- [select] インデックスを設定していない全文検索のパフォーマンスを改善しました。

- [関数] 全ての引数が他のテーブルへの参照か、リテラルである関数のパフォーマンスを改善しました。

- [インデックス構築] トークンカラムを使った静的インデックス構築のパフォーマンスを改善しました。 [GitHub#1126][naoaさんがパッチ提供]

- `"_score = func(...)"` のパフォーマンスを改善しました。

  - `_score` の値が `"_score = func(...)"` のように関数によってのみ算出される場合のパフォーマンスを改善しました。

### 修正

- 応答送信のエラーが発生した後の応答にゴミが含まれることがある問題を修正しました。

  - これは、クライアントが全ての応答を読み込まずにコネクションがクローズされた場合に発生することがあります。

### 感謝

- gaeeyoさん

- naoaさん

## 10.0.5リリース - 2020-07-30

### 改良

- [select] `-load_table` で指定したテーブルに参照を格納できるようにしました。

  - `--load-table` は予め用意したテーブルに検索結果を格納する機能です。

    - 複数回検索が実行される場合、このテーブルに結果を格納することで、検索結果をキャッシュできます。

    - このテーブルを使うことで、初回以降の検索時間を短縮できます。

  - 今回のリリース以降で、以下のようにこのテーブルに別のテーブルへの参照を格納できます。

    - カラムの値を格納せず、参照のみを格納するため、このテーブルのサイズを小さくすることができます。

    - このテーブルに対して検索する場合、参照先のテーブルのインデックスを使って検索できます。

        table_create Logs TABLE_HASH_KEY ShortText
        column_create Logs timestamp COLUMN_SCALAR Time

        table_create Times TABLE_PAT_KEY Time
        column_create Times logs_timestamp COLUMN_INDEX Logs timestamp

        table_create LoadedLogs TABLE_HASH_KEY Logs

        load --table Logs
        [
        {
          "_key": "2015-02-03:1",
          "timestamp": "2015-02-03 10:49:00"
        },
        {
          "_key": "2015-02-03:2",
          "timestamp": "2015-02-03 12:49:00"
        },
        {
          "_key": "2015-02-04:1",
          "timestamp": "2015-02-04 00:00:00"
        }
        ]

        select \
          Logs \
          --load_table LoadedLogs \
          --load_columns "_key" \
          --load_values "_key" \
          --limit 0

        select \
          --table LoadedLogs \
          --filter 'timestamp >= "2015-02-03 12:49:00"'
        [
          [
            0,
            0.0,
            0.0
          ],
          [
            [
              [
                2
              ],
              [
                [
                  "_id",
                  "UInt32"
                ],
                [
                  "_key",
                  "ShortText"
                ],
                [
                  "timestamp",
                  "Time"
                ]
              ],
              [
                2,
                "2015-02-03:2",
                1422935340.0
              ],
              [
                3,
                "2015-02-04:1",
                1422975600.0
              ]
            ]
          ]
        ]

- [select] 以下のケースのソートのパフォーマンスを改善しました。

  - 多くのソートキーがID解決をする場合。

    - 例えば、以下の式はIDを解決する必要があります。

      - `--filter true --sort_keys column`

    - 例えば、以下の式はIDを解決する必要がありません。 擬似カラム `_score` は、結果テーブルに存在しており、ソーステーブルには存在しないためIDを解決する必要がありません。

      - `--filter true --sort_keys _score`

  - ソート対象のテーブルがキーを持っている場合。

    - したがって、 `TABLE_NO_KEY` はこの改善をサポートしていません。

- [select] 以下のケースのパフォーマンスを少し改善しました。

  - 沢山のレコードがマッチする検索をしているケース。

  - 沢山のレコードに対してドリルダウンするケース。

- [aggregator] score アクセサーをサポートしました。[GitHub#1120][naoaさんのパッチ提供]

  - 例えば、 以下のように `_score` を `aggregator_*` の対象にできます。

        table_create Items TABLE_HASH_KEY ShortText
        column_create Items price COLUMN_SCALAR UInt32
        column_create Items tag COLUMN_SCALAR ShortText

        load --table Items
        [
        {"_key": "Book",  "price": 1000, "tag": "A"},
        {"_key": "Note",  "price": 1000, "tag": "B"},
        {"_key": "Box",   "price": 500,  "tag": "B"},
        {"_key": "Pen",   "price": 500,  "tag": "A"},
        {"_key": "Food",  "price": 500,  "tag": "C"},
        {"_key": "Drink", "price": 300,  "tag": "B"}
        ]

        select Items \
          --filter true \
          --drilldowns[tag].keys tag \
          --drilldowns[tag].output_columns _key,_nsubrecs,score_mean \
          --drilldowns[tag].columns[score_mean].stage group \
          --drilldowns[tag].columns[score_mean].type Float \
          --drilldowns[tag].columns[score_mean].flags COLUMN_SCALAR \
          --drilldowns[tag].columns[score_mean].value 'aggregator_mean(_score)'
        [
          [
            0,
            0.0,
            0.0
          ],
          [
            [
              [
                6
              ],
              [
                [
                  "_id",
                  "UInt32"
                ],
                [
                  "_key",
                  "ShortText"
                ],
                [
                  "price",
                  "UInt32"
                ],
                [
                  "tag",
                  "ShortText"
                ]
              ],
              [
                1,
                "Book",
                1000,
                "A"
              ],
              [
                2,
                "Note",
                1000,
                "B"
              ],
              [
                3,
                "Box",
                500,
                "B"
              ],
              [
                4,
                "Pen",
                500,
                "A"
              ],
              [
                5,
                "Food",
                500,
                "C"
              ],
              [
                6,
                "Drink",
                300,
                "B"
              ]
            ],
            {
              "tag": [
                [
                  3
                ],
                [
                  [
                    "_key",
                    "ShortText"
                  ],
                  [
                    "_nsubrecs",
                    "Int32"
                  ],
                  [
                    "score_mean",
                    "Float"
                  ]
                ],
                [
                  "A",
                  2,
                  1.0
                ],
                [
                  "B",
                  3,
                  1.0
                ],
                [
                  "C",
                  1,
                  1.0
                ]
              ]
            }
          ]
        ]

- [インデックス構築] VC++版の静的インデックス構築のパフォーマンスを改善しました。

- [select] JSON形式で出力する際に `NaN` や `Infinity` 、 `-Infinity` の代わりに `null` を出力するようにしました。

  - これらの値はJSONではサポートされていないためです。

- [select] 標準偏差の集計をサポートしました。

  - 例えば、以下のようにグループごとの標準偏差を計算できます。

        table_create Items TABLE_HASH_KEY ShortText
        column_create Items price COLUMN_SCALAR UInt32
        column_create Items tag COLUMN_SCALAR ShortText

        load --table Items
        [
        {"_key": "Book",  "price": 1000, "tag": "A"},
        {"_key": "Note",  "price": 1000, "tag": "B"},
        {"_key": "Box",   "price": 500,  "tag": "B"},
        {"_key": "Pen",   "price": 500,  "tag": "A"},
        {"_key": "Food",  "price": 500,  "tag": "C"},
        {"_key": "Drink", "price": 300,  "tag": "B"}
        ]

        select Items \
          --drilldowns[tag].keys tag \
          --drilldowns[tag].output_columns _key,_nsubrecs,price_sd \
          --drilldowns[tag].columns[price_sd].stage group \
          --drilldowns[tag].columns[price_sd].type Float \
          --drilldowns[tag].columns[price_sd].flags COLUMN_SCALAR \
          --drilldowns[tag].columns[price_sd].value 'aggregator_sd(price)' \
          --output_pretty yes
        [
          [
            0,
            1594339851.924836,
            0.002813816070556641
          ],
          [
            [
              [
                6
              ],
              [
                [
                  "_id",
                  "UInt32"
                ],
                [
                  "_key",
                  "ShortText"
                ],
                [
                  "price",
                  "UInt32"
                ],
                [
                  "tag",
                  "ShortText"
                ]
              ],
              [
                1,
                "Book",
                1000,
                "A"
              ],
              [
                2,
                "Note",
                1000,
                "B"
              ],
              [
                3,
                "Box",
                500,
                "B"
              ],
              [
                4,
                "Pen",
                500,
                "A"
              ],
              [
                5,
                "Food",
                500,
                "C"
              ],
              [
                6,
                "Drink",
                300,
                "B"
              ]
            ],
            {
              "tag": [
                [
                  3
                ],
                [
                  [
                    "_key",
                    "ShortText"
                  ],
                  [
                    "_nsubrecs",
                    "Int32"
                  ],
                  [
                    "price_sd",
                    "Float"
                  ]
                ],
                [
                  "A",
                  2,
                  250.0
                ],
                [
                  "B",
                  3,
                  294.3920288775949
                ],
                [
                  "C",
                  1,
                  0.0
                ]
              ]
            }
          ]
        ]

    - `aggregate_sd(target, {"unbiased": true})` と指定することで、不偏標準偏差も計算できます。

- [Windows] Visual Studio 2013のサポートをやめました。

### 修正

- [Groonga HTTPサーバー] 応答がエラーで中断された時に、 `shutdown?immediate` を実行しても、リクエストが中断しない問題を修正しました。

- リクエスト中にエラーが発生した時にクラッシュする問題を修正しました。

  - これは、Apache Arrow形式を使っている時にのみ発生します。

  - 前のリクエストがエラーによって中断された後に再度Groongaへリクエストを送信した時にGroongaがクラッシュします。

- [between] 一時テーブルを使用した時にクラッシュする問題を修正しました。

  - 例えば、 `between` の第一引数に動的カラムを指定すると、Groongaがクラッシュしていました。

- プラグインで作成したプロシージャーが予期せず解放される問題を修正しました。

  - 参照カウントモードでのみ発生します。

  - `plugin_register` を使っていない場合は、発生しません。

  - `plugin_register` を実行したプロセスでは発生しません。

  - `plugin_register` を実行していないプロセスで発生します。

- `token_column` を使った静的インデックス構築中に正規化エラーが発生する問題を修正しました。[GitHub#1122][naoaさんの報告]

### 感謝

- naoaさん

## 10.0.4リリース - 2020-06-29

### 改良

- [テーブル] ハッシュテーブルで4億件のレコードの登録をサポートしました。

- [select] `_score` が再帰的に値を取得しない時のパフォーマンスを改善しました。

  - Groongaは、検索結果が検索対象の時に、 `_score` の値を再帰的に取得します。

  - 例えば、 `slices` は検索結果が検索対象です。したがって、 `slices` を使っているクエリーでは、この改善は効果がありません。

- [ログ] ドリルダウンのキーをクエリーログに出力するようにしました。

- [reference_acquire], [reference_release] 参照カウントモード用に新しいコマンドを追加しました。

  - 短い間隔で複数の `load` を呼び出す必要がある場合、参照カウントモードによる自動クローズによってパフォーマンスが低下します。

  - 複数の `load` の前に `reference_acquire` を呼び、 複数の `load` の後に `reference_release` を呼ぶことで、このパフォーマンスの低下を避けることができます。`reference_acquire` と `reference_release` の間は自動クローズは無効になります。

    - `reference_acquire` が、対象のオブジェクトの参照を取得するためです。

  - パフォーマンスに影響のある操作が完了したら、 `reference_release` を呼ぶ必要があります。

  - `reference_release` を呼ばない場合、参照カウントモードは機能しません。

- [select] 一度の `drilldown` で複数グループの集計をサポートしました。

  - 以下のように、一回の `drilldown` で異なるグループ毎に和と算術平均を計算できるようになりました。

        table_create Items TABLE_HASH_KEY ShortText
        column_create Items price COLUMN_SCALAR UInt32
        column_create Items quantity COLUMN_SCALAR UInt32
        column_create Items tag COLUMN_SCALAR ShortText

        load --table Items
        [
        {"_key": "Book",  "price": 1000, "quantity": 100, "tag": "A"},
        {"_key": "Note",  "price": 1000, "quantity": 10,  "tag": "B"},
        {"_key": "Box",   "price": 500,  "quantity": 15,  "tag": "B"},
        {"_key": "Pen",   "price": 500,  "quantity": 12,  "tag": "A"},
        {"_key": "Food",  "price": 500,  "quantity": 111, "tag": "C"},
        {"_key": "Drink", "price": 300,  "quantity": 22,  "tag": "B"}
        ]

        select Items \
          --drilldowns[tag].keys tag \
          --drilldowns[tag].output_columns _key,_nsubrecs,price_sum,quantity_sum \
          --drilldowns[tag].columns[price_sum].stage group \
          --drilldowns[tag].columns[price_sum].type UInt32 \
          --drilldowns[tag].columns[price_sum].flags COLUMN_SCALAR \
          --drilldowns[tag].columns[price_sum].value 'aggregator_sum(price)' \
          --drilldowns[tag].columns[quantity_sum].stage group \
          --drilldowns[tag].columns[quantity_sum].type UInt32 \
          --drilldowns[tag].columns[quantity_sum].flags COLUMN_SCALAR \
          --drilldowns[tag].columns[quantity_sum].value 'aggregator_sum(quantity)'
        [
          [
            0,
            0.0,
            0.0
          ],
          [
            [
              [
                6
              ],
              [
                [
                  "_id",
                  "UInt32"
                ],
                [
                  "_key",
                  "ShortText"
                ],
                [
                  "price",
                  "UInt32"
                ],
                [
                  "quantity",
                  "UInt32"
                ],
                [
                  "tag",
                  "ShortText"
                ]
              ],
              [
                1,
                "Book",
                1000,
                100,
                "A"
              ],
              [
                2,
                "Note",
                1000,
                10,
                "B"
              ],
              [
                3,
                "Box",
                500,
                15,
                "B"
              ],
              [
                4,
                "Pen",
                500,
                12,
                "A"
              ],
              [
                5,
                "Food",
                500,
                111,
                "C"
              ],
              [
                6,
                "Drink",
                300,
                22,
                "B"
              ]
            ],
            {
              "tag": [
                [
                  3
                ],
                [
                  [
                    "_key",
                    "ShortText"
                  ],
                  [
                    "_nsubrecs",
                    "Int32"
                  ],
                  [
                    "price_sum",
                    "UInt32"
                  ],
                  [
                    "quantity_sum",
                    "UInt32"
                  ]
                ],
                [
                  "A",
                  2,
                  1500,
                  112
                ],
                [
                  "B",
                  3,
                  1800,
                  47
                ],
                [
                  "C",
                  1,
                  500,
                  111
                ]
              ]
            }
          ]
        ]

- [groonga-httpd] スタンドアローンモードで、 `--pid-path` をサポートしました。

  - 以前のバージョンのスタンドアローンモードでは、 `--pid-path` は無視されていました。

- [io_flush] 参照カウントモードに対応しました。

- [logical_range_filter],[logical_count] 参照カウントモードに対応しました。

- [Groonga HTTPサーバー] 最後のチャンクの後にヘッダーをつけないようにしました。

  - 最後のチャンクの後のヘッダーを無視するHTTPクライアントが存在する可能性があるためです。

- [vector_slice] `Float32` 型のベクターをサポートしました。 [GitHub#1106 naoaさんがパッチ提供]

- トークンカラムを使った、並列静的インデックス構築をサポートしました。

  - 予めトークナイズされたデータから複数スレッドで静的インデックスの構築ができるようになりました。

  - 以下の環境変数で、並列静的インデックス構築のパラメータを調整できます。

    - `GRN_TOKEN_COLUMN_PARALLEL_CHUNK_SIZE` : スレッド毎にどのくらいのレコードを処理するかを指定します。

      - デフォルト値は `1024` レコードです。

    - `GRN_TOKEN_COLUMN_PARALLEL_TABLE_SIZE_THRESHOLD` : どのくらいのソースレコードで並列化するかを指定します。

      - デフォルト値は `102400` レコードです。

- [select] 参照カウントモード時の `load_table` のパフォーマンスを改善しました。

### 修正

- シャードをまたいでいて、かつ `--filter` を指定していない動的カラムを使って検索すると、Gronngaのデータベースが破損する問題を修正しました。

- `schema` コマンドの結果に `Float32` 型が表示されなかった問題を修正しました。

- 参照 `uvector` が要素を持っていないとき、 `_nsubrecs` を余分にカウントする問題を修正しました。

### 感謝

- naoaさん

## 10.0.3リリース - 2020-05-29

### 改良

- 予めトークナイズされたデータから転置インデックスを構築できるようになりました。

  - これにより、インデックスの構築が高速化します。

  - この改善を使うには、トークンカラムを準備する必要があります。

  - トークンカラムは、インデックスカラムのように自動で値が生成されます。

  - トークンカラムの値はソースカラムの値をトークナイズすることで生成されます。

  - トークンカラムは以下のようにソースカラムを設定することで作成できます。

        table_create Terms TABLE_PAT_KEY ShortText \
          --normalizer NormalizerNFKC121 \
          --default_tokenizer TokenNgram

        table_create Notes TABLE_NO_KEY
        column_create Notes title COLUMN_SCALAR Text

        # The last "title" is the source column.
        column_create Notes title_terms COLUMN_VECTOR Terms title

- [select] 関数の引数に `vector` を指定できるようになりました。

  - 例えば、 `query` の `flags` オプションを `vector` を使って以下のように記述できます。

        select \
          --table Memos \
          --filter 'query("content", "-content:@mroonga", \
                          { \
                            "expander": "QueryExpanderTSV", \
                            "flags": ["ALLOW_LEADING_NOT", "ALLOW_COLUMN"] \
                          })'

- [select] 動的カラムに新しいステージ `result_set` を追加しました。

  - このステージは、結果セットのテーブルにカラムを作ります。したがって、 `query` か `filter` が存在しない場合は作られません。

    - `query` や `filter` が存在しない場合は、結果セットのテーブルが作られないためです。

  - このステージでは `_value` は使用できません。 `result_set` ステージの値は `score_column` に格納されます。

- [vector_slice] 重み付きベクターの重みに `Float32` 型が使えるようになりました。 [GitHub#1106 naoaさんがパッチ提供]

- [select] drilldownsの動的カラムのステージに `filtered` と `output` を追加しました。 [GitHub#1101 naoaさんがパッチ提供][GitHub#1100 naoaさんがパッチ提供]

  - `drilldowns[Label].stage filtered` や `drilldowns[Label].stage output` のように drilldowns の動的カラムのステージに `filtered` と `output` を使えます。

- [select] ドリルダウンでの集計に `Float` 型の値をサポートしました。

  - `MAX`、`MIN`、`SUM` を使って `Float` 型の値の最大値、最小値、合計値を集計できます。

- [query] [geo_in_rectangle] [geo_in_circle] `query()` と `geo_in_rectangle()` と `geo_in_circle()` に新しいオプション `score_column` を追加しました。

  - `score_column` を使うことで条件毎にスコアの値を格納できます。

  - 通常、Groongaは、全ての条件のスコアーを加算してスコアーを計算しますが、条件毎にスコアーの値を取得したいこともあります。

  - 例えば以下のように、中心座標にどれだけ近いかをスコアーとして使いたい場合に `score_column` が使えます。

      table_create LandMarks TABLE_NO_KEY
      column_create LandMarks name COLUMN_SCALAR ShortText
      column_create LandMarks category COLUMN_SCALAR ShortText
      column_create LandMarks point COLUMN_SCALAR WGS84GeoPoint

      table_create Points TABLE_PAT_KEY WGS84GeoPoint
      column_create Points land_mark_index COLUMN_INDEX LandMarks point

      load --table LandMarks
      [
        {"name": "Aries"      , "category": "Tower"     , "point": "11x11"},
        {"name": "Taurus"     , "category": "Lighthouse", "point": "9x10" },
        {"name": "Gemini"     , "category": "Lighthouse", "point": "8x8"  },
        {"name": "Cancer"     , "category": "Tower"     , "point": "12x12"},
        {"name": "Leo"        , "category": "Tower"     , "point": "11x13"},
        {"name": "Virgo"      , "category": "Temple"    , "point": "22x10"},
        {"name": "Libra"      , "category": "Tower"     , "point": "14x14"},
        {"name": "Scorpio"    , "category": "Temple"    , "point": "21x9" },
        {"name": "Sagittarius", "category": "Temple"    , "point": "43x12"},
        {"name": "Capricorn"  , "category": "Tower"     , "point": "33x12"},
        {"name": "Aquarius"   , "category": "mountain"  , "point": "55x11"},
        {"name": "Pisces"     , "category": "Tower"     , "point": "9x9"  },
        {"name": "Ophiuchus"  , "category": "mountain"  , "point": "21x21"}
      ]

      select LandMarks \
        --sort_keys 'distance' \
        --columns[distance].stage initial \
        --columns[distance].type Float \
        --columns[distance].flags COLUMN_SCALAR \
        --columns[distance].value 0.0 \
        --output_columns 'name, category, point, distance, _score' \
        --limit -1 \
        --filter 'geo_in_circle(point, "11x11", "11x1", {"score_column": distance}) && category == "Tower"'
      [
        [
          0,
          1590647445.406149,
          0.0002503395080566406
        ],
        [
          [
            [
              5
            ],
            [
              [
                "name",
                "ShortText"
              ],
              [
                "category","ShortText"
              ],
              [
                "point",
                "WGS84GeoPoint"
              ],
              [
                "distance",
                "Float"
              ],
              [
                "_score",
                "Int32"
              ]
            ],
            [
              "Aries",
              "Tower",
              "11x11",
              0.0,
              1
            ],
            [
              "Cancer",
              "Tower",
              "12x12",
              0.0435875803232193,
              1
            ],
            [
              "Leo",
              "Tower",
              "11x13",
              0.06164214760065079,
              1
            ],
            [
              "Pisces",
              "Tower",
              "9x9",
              0.0871751606464386,
              1
            ],
            [
              "Libra",
              "Tower",
              "14x14",
              0.1307627409696579,
              1
            ]
          ]
        ]
      ]

  - 上記の例では、 `_score` によるソートは意味をなしません。 `category == "Tower"` によって、 `_score` の値は全て `1` になるためです。しかし、 `socre_column` を使うことで、中心座標からの距離でソートできます。

- [Windows] クラッシュしていないくてもエラー時にはバックトレースが出力されるようになりました。

- [Windows] 古いWindowsのサポートをやめました。

  - 10.0.3から、Windows 8 (Windows Server 2012) 以降を要求します。

- [select] 参照可能なソートキーとそうでないソートキーが混在しているときのソートパフォーマンスを改善しました。

  - 参照可能なソートキーとそうでないソートキーが混在していて、参照可能なキーが2つ以上あるときのソートパフォーマンスを改善しました。

    - 参照可能なソートキーとは以下のソートキー以外のことです。

      - 圧縮されたカラム

      - ドリルダウンのキーに複数の値が指定されているドリルダウンの値を格納する `_value`

      - `ShortText` 型のキーを持たないパトリシアトライテーブルの `_key`

      - `_score`

  - 文字列以外のソートキーが多いほど、ソートに使用するメモリ使用量が少なくなります。

- [select] 全てのソートキーが参照可能なキーの時のソートのパフォーマンスを改善しました。

- [select] `_socre = column1*X + column2*Y + ...` の場合のスコアラーのパフォーマンスを改善しました。

  - この最適化は、 `_score` 内に多くの `+` または `*` がある場合に効きます。

  - 現状、 `+` と `*` に対してのみ効果があります。

- [select] フレーズ近傍検索をサポートしました。

  - フレーズ単位で近傍検索できます。

    - フレーズ近傍検索のクエリー構文は、 `*NP"Phrase1 phrase2 ..."` です。

    - フレーズ近傍検索のスクリプト構文は、 `column *NP "phrase1 phrase2 ..."` です。

    - 検索対象のフレーズにスペースを含む場合、 以下のようにフレーズを `"` で囲うことで検索できます。

          table_create Entries TABLE_NO_KEY
          column_create Entries content COLUMN_SCALAR Text

          table_create Terms TABLE_PAT_KEY ShortText \
            --default_tokenizer 'TokenNgram("unify_alphabet", false, \
                                            "unify_digit", false)' \
            --normalizer NormalizerNFKC121
          column_create Terms entries_content COLUMN_INDEX|WITH_POSITION Entries content

          load --table Entries
          [
          {"content": "I started to use Groonga. It's very fast!"},
          {"content": "I also started to use Groonga. It's also very fast! Really fast!"}
          ]

          select Entries --filter 'content *NP "\\"I started\\" \\"use Groonga\\""' --output_columns 'content'
          [
            [
              0,
              1590469700.715882,
              0.03997230529785156
            ],
            [
              [
                [
                  1
                ],
                [
                  [
                    "content",
                    "Text"
                  ]
                ],
                [
                  "I started to use Groonga. It's very fast!"
                ]
              ]
            ]
          ]

- [ベクターカラム] 重み付きベクターの重みに `float32` 型を追加しました。

  - `uint32` の代わりに `float32` として重みを格納できます。

  - この機能を使うには、 `column_create` 実行時に `WEIGHT_FLOAT32` フラグを追加する必要があります。

        column_create Records tags COLUMN_VECTOR|WITH_WEIGHT|WEIGHT_FLOAT32 Tags

  - 今の所、 `WEIGHT_FLOAT32` フラグは、 `COLUMN_INDEX` フラグと併用できません。

- 以下のAPIを公開しました。

  - `grn_obj_is_xxx` 関数を追加しました。詳細は以下の通りです。

    - `grn_obj_is_weight_vector(grn_ctx *ctx, grn_obj *obj)`

      - 重み付きベクターかどうかを `bool` として返します。

    - `grn_obj_is_uvector(grn_ctx *ctx, grn_obj *obj)`

      - `uvector` かどうかを `bool` として返します。

        - `uvector` とは、要素のサイズが固定の `vector` です。

    - `grn_obj_is_weight_uvector(grn_ctx *ctx, grn_obj *obj)`

      - 重み付きuvectorかどうかを `bool` として返します。

  - `grn_type_id_size(grn_ctx *ctx, grn_id id)` を追加しました。

    - Groongaのデータ型のサイズを `size_t` として返します。

  - `grn_selector_data_get_xxx` を追加しました。詳細は以下の通りです。

    - これらの関数はセレクター関連のデータを返します。

      - これらの関数はセレクターの中で呼び出すことを想定しています。セレクター以外の場所で呼び出された場合は、 `NULL` を返します。

        - `grn_selector_data_get(grn_ctx *ctx)`

          - セレクター呼び出しに関する全ての情報を `grn_selector_data *` 構造体として返します。

        - `grn_selector_data_get_selector(grn_ctx *ctx, grn_selector_data *data)`

          - セレクター自身を `grn_obj *` として返します。

        - `grn_selector_data_get_expr(grn_ctx *ctx, grn_selector_data *data)`

          - セレクターに使用されている、 `--filter` 条件や `--query` 条件を `grn_obj *` として返します。

        - `grn_selector_data_get_table(grn_ctx *ctx, grn_selector_data *data)`

          - 検索対象のテーブルを `grn_obj *` として返します。

        - `grn_selector_data_get_index(grn_ctx *ctx, grn_selector_data *data)`

          - セレクターに使われているインデックスを `grn_obj *` として返します。

        - `grn_selector_data_get_args(grn_ctx *ctx, grn_selector_data *data, size_t *n_args)`

          - セレクターが呼び出した関数の引数を `grn_obj *` として返します。

        - `grn_selector_data_get_result_set(grn_ctx *ctx, grn_selector_data *data)`

          - 結果テーブルを `grn_obj *` として返します。

        - `grn_selector_data_get_op(grn_ctx *ctx, grn_selector_data *data)`

          - 既存の結果セットに対してどう集合演算したかを `grn_operator` として返します。

  - `grn_plugin_proc_xxx` 関数を追加しました。詳細は以下の通りです。

    - `grn_plugin_proc_get_value_operator(grn_ctx *ctx, grn_obj *value, grn_operator default_operator, const char *context)`

      - クエリーオペレーターを `grn_operator` として返します。

        - 例えば、 `&&` は `GRN_OP_ANDP` として返されます。

    - `grn_plugin_proc_get_value_bool(grn_ctx *ctx, grn_obj *value, bool default_value, const char *tag)`

      - 以下の関数の引数 `with_transposition` のように `true` または `false` が指定される値を `bool` として返します。( `bool` はC言語のデータ型です。)

            fuzzy_search(column, query, {"max_distance": 1, "prefix_length": 0, "max_expansion": 0, "with_transposition": true})

  - `grn_proc_options_xxx` 関数を追加しました。詳細は以下の通りです。

    - これらは、 `query()` でのみ使えます。

      - `grn_proc_options_parsev(grn_ctx *ctx, grn_obj *options, const char *tag, const char *name, va_list args)` を追加しました。

        - オプションのパースを実行します。

        - 今までは、オプションのパースを自分で実装しなければなりませんでしたが、この関数を呼び出すだけでオプションをパースできます。

      - `grn_proc_options_parse(grn_ctx *ctx, grn_obj *options, const char *tag, const char *name, ...)`

        - `grn_proc_option_parsev()` を呼び出します。したがって、この関数の機能は、 `grn_proc_options_parsev()` と同じです。

        - `grn_proc_options_parsev()` とは、インターフェースだけが異なります。

  - `grn_text_printfv(grn_ctx *ctx, grn_obj *bulk, const char *format, va_list args)` を追加しました。

    - `grn_text_vprintf` は10.0.3から非推奨になりました。 代わりに `grn_text_printfv` を使ってください。

  - `grn_type_id_is_float_family(grn_ctx *ctx, grn_id id)` を追加しました。

    - `grn_type_id` が `GRN_DB_FLOAT32` または `GRN_DB_FLOAT` かどうかを `bool` として返します。

  - `grn_dat_cursor_get_max_n_records(grn_ctx *ctx, grn_dat_cursor *c)` を追加しました。

    - カーソルが保持できるレコード数の最大値を `size_t` として返します。(このAPIはDATテーブル用です。)

  - `grn_table_cursor_get_max_n_records(grn_ctx *ctx, grn_table_cursor *cursor)` を追加しました。

    - カーソルが保持できるレコード数の最大値を返します。

    - 全ての種類(`TABLE_NO_KEY`, `TABLE_HASH_KEY`, `TABLE_DAT_KEY`, `TABLE_PAT_KEY`)のテーブルで使えます。

  - `grn_result_set_add_xxx` を追加しました。詳細は以下の通りです。

    - `grn_result_set_add_record(grn_ctx *ctx, grn_hash *result_set, grn_posting *posting, grn_operator op)`

      - 結果セットのテーブルにレコードを追加します。

      - `grn_ii_posting_add_float` は10.0.3から非推奨になりました。代わりに `grn_rset_add_records()` を使ってください。

    - `grn_result_set_add_table(grn_ctx *ctx, grn_hash *result_set, grn_obj *table, double score, grn_operator op)`

      - 結果セットにテーブルを追加します。

    - `grn_result_set_add_table_cursor(grn_ctx *ctx, grn_hash *result_set, grn_table_cursor *cursor, double score, grn_operator op)`

      - 結果セットにカーソル内のレコードを追加します。

  - `grn_vector_copy(grn_ctx *ctx, grn_obj *src, grn_obj *dest)` を追加しました。

    - `vector` オブジェトをコピーします。 `vector` オブジェクトのコピーに成功したかどうかを返します。

  - `grn_obj_have_source(grn_ctx *ctx, grn_obj *obj)` を追加しました。

    - ソースカラムを持つカラムかどうかを `bool` として返します。

  - `grn_obj_is_token_column(grn_ctx *ctx, grn_obj *obj)` を追加しました。

    - トークンカラムかどうかを `bool` として返します。

  - `grn_hash_add_table_cursor(grn_ctx *ctx, grn_hash *hash, grn_table_cursor *cursor, double score)` を追加しました。

    - 結果セットを一括して挿入するための関数です。 `grn_ii_posting_add()` を使ってレコードを挿入するより高速です。

### 修正

- 複数のスレッドから、同時にモジュール(トークナイザー、ノーマライザー、トークンフィルター)が使われた場合にクラッシュする問題を修正しました。

- `Float32` の値を表示する際の精度を修正しました。

  - 10.0.3から `Float32` の値の精度は、 8桁から7桁になります。

- 動的カラムのパラメーターだけが違うクエリーが実行された時にGroongaが誤ったキャッシュを使用していた問題を修正しました。 [GitHub#1102 naoaさんがパッチ提供]

### 感謝

- naoaさん

## 10.0.2リリース - 2020-04-29

### 改良

- `time_classify_*` 関数が `uvector` に対応しました。 [GitHub#1089][naoaさんがパッチ提供]

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

  - 例えば、Time型の要素を格納しているベクターは `uvector` です。

- ゼロコピーで値を参照できないソートキーが混在しているケースでソートのパフォーマンスを改善しました。

  - いくつかのソートキー(例えば、 `_score` 等)の値はゼロコピーで値を参照できません。

  - これらの値が一つでも含まれる場合、以前は全てのソートキーの値をコピーしていました。

  - 今回の変更から、参照できないソートキーの値だけコピーし、参照可能なソートキーの値はコピーせずに参照するようにしました。

  - ただ、この変更で全てのソートキーの値が参照可能なケースでパフォーマンスが落ちる可能性があります。

- 重み付きベクターをJSON文字列としてロードできるようにしました。

  - 以下の例のように、重み付きベクターをJSON文字列としてロードできます。

        table_create Tags TABLE_PAT_KEY ShortText
        table_create Data TABLE_NO_KEY
        column_create Data tags COLUMN_VECTOR|WITH_WEIGHT Tags
        column_create Tags data_tags COLUMN_INDEX|WITH_WEIGHT Data tags
        load --table Data
        [
          {"tags": "{\"fruit\": 10, \"apple\": 100}"},
          {"tags": "{\"fruit\": 200}"}
        ]

- `Float32` 型をサポートしました。

  - Groongaは既に `Float` 型を持っていますが、これは、倍精度浮動小数点数です。したがって、単精度浮動小数点数のみを使う場合は、効率が悪いです。

  - `Float32` 型を追加することで、より適切な型を選択できるようになりました。

- 以下のAPIを公開しました。

  - `grn_obj_unref(grn_ctx *ctx, grn_obj *obj)`

    - このAPIは参照カウントモードのときのみ使用します。(参照カウントモードとは、 `GRN_ENABLE_REFERENCE_COUNT=yes` の状態のことです。)

      - このAPIは、参照カウントモードの時のみ `grn_obj_unlink()` を呼び出します。参照カウントモード以外の時は、何もしません。

      - 参照カウントモードの時のみ `grn_obj_unlink()` を呼び出す必要がある時に便利です。

      - 以下の例のように、参照カウントモードかどうかの条件を書かなくて良くなるためです。

        - `grn_obj_unref()` を使用しない場合の例です。

              if (grn_enable_reference_count) {
               grn_obj_unlink(ctx, obj);
              }

        - `grn_obj_ubref()` を使用する場合の例です。

              grn_obj_ubref(ctx, obj);

  - `grn_get_version_major(void)`

  - `grn_get_version_minor(void)`

  - `grn_get_version_micro(void)`

    - `uint32_t` としてGroongaのメジャー、マイナー、マイクロバージョンを返します。

  - `grn_posting_get_record_id(grn_ctx *ctx, grn_posting *posting)`

  - `grn_posting_get_section_id(grn_ctx *ctx, grn_posting *posting)`

  - `grn_posting_get_position(grn_ctx *ctx, grn_posting *posting)`

  - `grn_posting_get_tf(grn_ctx *ctx, grn_posting *posting)`

  - `grn_posting_get_weight(grn_ctx *ctx, grn_posting *posting)`

  - `grn_posting_get_weight_float(grn_ctx *ctx, grn_posting *posting)`

  - `grn_posting_get_rest(grn_ctx *ctx, grn_posting *posting)`

    - これらは、ポスティングリストの情報を返します。

    - これらのAPIは、 `grn_posting_get_weight_float` 以外は、 `uint32_t` として値を返します。

    - `grn_posting_get_weight_float` は `float` として値を返します。

    - `grn_posting_get_section_id(grn_ctx *ctx, grn_posting *posting)`

      - セクションIDとはカラム名の内部表現です。

      - カラム名を文字列としてポスティングリストに格納すると、情報量が多くなり無駄な容量を使います。

      - したがって、カラム名をセクションIDという数値としてポスティングリストに格納することで、情報量を圧縮し使用する容量を少なくしています。

    - `grn_posting_get_tf(grn_ctx *ctx, grn_posting *posting)`

      - `grn_posting_get_tf` の `tf` とは、単語の出現頻度です。

    - `grn_posting_get_weight_float(grn_ctx *ctx, grn_posting *posting)`

      - トークンの重みを `float` として返します。

      - 今後はトークンの重みを取得する際はこのAPIを使用することをおすすめします。

        - 近い将来、重みは内部的に `uint32_t` から `float` に変更するためです。

### 修正

- 32bit GUN/Linux等でGroongaがクラッシュすることがある問題を修正しました。

- 関係のないカラムの値をクリアーしてしまう問題を修正しました。 [GitHub#1087][sutaminさんの報告]

- `dump` コマンドでレコードをダンプした時にメモリリークする問題を修正しました。

- `output_columns` に無効な値を指定した時にメモリリークする問題を修正しました。

- `snippet` 関数を実行する時にメモリリークする問題を修正しました。

- 以下の条件を満たした時にメモリリークする問題を修正しました。

  - `initial` ステージで動的カラムを使用した場合。

  - `select` コマンドの引数 `slices` を使用した場合。

- `logical_table_remove` でテーブルを削除した際にメモリリークする問題を修正しました。

- 参照カウントモードを使用した時にメモリリークする問題を修正しました。

  - 参照カウントモードとは、 `GRN_ENABLE_REFERENCE_COUNT=yes` の状態のことです。

  - この機能は実験的です。パフォーマンスが低下することがあります。

- Apache Arrow形式でデータをロードした際に `_key` アクセサーを解放しすぎる問題を修正しました。

### 感謝

- sutaminさん

- naoaさん

## 10.0.1リリース - 2020-03-30

Groonga 10.0.0 のUbuntuとWindows(VC++版)のパッケージに誤りがあったため Groonga 10.0.1 をリリースしました。

既にCentOS、Debian、Windows(MinGW版)のGroonga 10.0.0を使用している方は、そのまま使っていただいて問題ありません。

### 修正

- Windows(VC++版)のパッケージに不足していたランタイム(vcruntime140_1.dll)を追加しました。

## 10.0.0リリース - 2020-03-29

### 改良

- [httpd] バンドルしているnginxのバージョンを1.17.9に更新しました。

- [httpd] 出力形式を拡張子として指定できるようにしました。

  - 例えば、 `load?output_type=json` の代わりに `load.json` と書けます。

- [ログ] Linuxのdumpレベルのログにオープンしたファイルとクローズしたファイルのパスを出力するようにしました。

- [ログ] Windowsのdebugレベルのログにオープンしたファイルとクローズしたファイルのパスを出力するようにしました。

- 以下のAPIとマクロを追加しました。

  - `grn_timeval_from_double(grn_ctx, double)`

    - このAPIは、 `double` 型を `grn_timeval` 型に変換します。

    - `grn_timeval` 型の値を返します。

  - `GRN_TIMEVAL_TO_NSEC(timeval)`

    - このマクロは、 `grn_timeval` 型の値を `uint64_t` 型の値としてナノ秒に変換します。

  - `GRN_TIME_USEC_TO_SEC(usec)`

    - このマクロは、ミリ秒を秒に変換します。

- 以下のマクロを非推奨にしました。

  - `GRN_OBJ_FORMAT_FIN(grn_ctx, grn_obj_format)`

    - 10.0.0から代わりに `grn_obj_format_fin(grn_ctx, grn_obj_format)` を使ってください。

- [logical_range_filter],[dump] ストリーム出力に対応しました。

  - この機能は `command_version 3` 以降で使えます。headerがbodyの後に出力されます。

  - 現在、この機能をサポートしているのは、 `dump` と `logical_range_filter` のみです。

  - `logical_range_filter` は、 `command_version 3` 以降では、常に出力がstreamとして返ります。

  - この機能は以下の制限があります。

    - `limit` に指定できる負の値は -1 のみです。

    - MessagePack形式の出力はサポートしていません。

  - この変更で、JSONの応答内容を少し変更しています。

    - 以下のように以前のバージョンとは、キーの順序が異なっています。

      - 以前のバージョンのキーの順序

            {
              "header": {...},
              "body": {...}
            }

      - 本バージョン(10.0.0)のキーの順序

            {
              "body": {...},
              "header": {...}
            }

  - `dump` と `logical_range_filter` を `command_version 3` で実行した時はキャッシュが効きません。

    - 10.0.0から `dump` と `logical_range_filter` は `command_version 3` の時にストリームで応答を返すので、応答全体をキャッシュできないためです。

- [logical_range_filter] Apache Arrow形式での応答をサポートしました。

  - 以下のデータ型をサポートしています。

    - `UInt8`

    - `Int8`

    - `UInt16`

    - `Int16`

    - `UInt32`

    - `Int32`

    - `UInt64`

    - `Int64`

    - `Time`

    - `ShortText`

    - `Text`

    - `LongText`

    - `Vector` of `Int32`

    - `Reference vector`

- Ubuntu 20.04 (Focal Fossa)をサポートしました。

- Ubuntu 19.04 (Disco Dingo)のサポートをやめました。

  - このバージョンはEOLになっているためです。

## 9.1.2リリース - 2020-01-29

### 改良

- [tools] 指定したテーブルまたはカラムのファイルのみをコピーするスクリプトを追加しました。

  - このスクリプトの名前は、copy-related-files.rbです。

  - このスクリプトは非常に大きいデータベースから指定したテーブルまたはカラムを抽出したい場合に便利です。

  - 特定のテーブルまたはカラムに関連するファイルは、障害の再現に必要なことがあります。

  - データベースをまるごと提供するのが難しい場合は、このツールを使って対象のテーブルまたはカラムに関連するファイルを抽出できます。

- [shutdown] 全てのスレッドが使われている場合でも、 `/d/shutdown?mode=immediate` を即時受け付けるようにしました。

  - この機能はGroonga HTTPサーバでのみ使えます。

- `GRN_ENABLE_REFERENCE_COUNT=yes` を使うと、使用していないオブジェクトをすぐに開放します。

  - この機能は実験的です。パフォーマンスが低下します。

  - 多くのテーブルにまたがるデータをロードする際等にメモリーの使用量を一定量に保つ効果が期待できます。

- [CentOS] `groonga-release` パッケージをバージョンごとに用意しました。

  - インストール方法に少し変更があるので注意してください。

- [Debian GNU/Linux] Groongaのaptリポジトリーの追加に `groonga-archive-keyring` を使うようにしました。

  - この改善によって、Groongaのaptリポジトリーを簡単に追加できます。

  - `groonga-archive-keyring` はGroongaのaptリポジトリーを使うための全ての情報が入っています。そのため、リポジトリー情報やPGPキーの変更を意識する必要がありません。

  - `groonga-archive-keyring` はdebパッケージなので、 `apt update` で簡単に更新できます。

## 9.1.1リリース - 2020-01-07

### 改良

- [load] Apache Arrow 形式のデータをサポートしました。

  - Apache Arrow形式のデータを使うことで、パースのコストを削減でき、他のフォーマットより高速にデータをロードできる可能性があります。

  - この変更によって、他のデータ分析システムからApache Arrow形式のデータを直接Groongaへ入力することもできます。

  - Apache Arrow形式のフォーマットはHTTPインターフェイスでのみ使えます。コマンドラインインターフェイスでは使えません。

- [load] Apache Arrow 形式のロード方法をドキュメントに追加しました。

- [load] エラーメッセージを改善しました。

  - `load` コマンドのレスポンスにエラーメッセージも含むようにしました。

  - この変更によって、データのロードに失敗した場合、 `load` コマンドのエラーの詳細を出力します。

- [httpd] バンドルしているnginxのバージョンを1.17.7に更新しました。

- [Groonga HTTPサーバー] HTTPリクエストのbodyにコマンドのパラメータを指定できるようにしました。

  - この場合、 `Content-Type` に `application/x-www-form-urlencoded` を指定しなければいけません。

- [Groonga HTTPサーバー] HTTP POST の使用方法をドキュメントに追加しました。

## 9.1.0リリース - 2019-11-29

### 改良

- "&&"演算のパフォーマンスを改善しました。

  - 例えば、以下のような条件式のパフォーマンスが向上します。

  - ( A || B ) && ( C || D ) && ( E || F) ...

- [TokenMecab] `TokenMecab` に `use_base_form` オプションを追加しました。

  - このオプションによってトークンの原型を使って検索できます。

  - 例えば、このオプションを使って"支えた"を検索した場合、"支える"もヒットします。

### 修正

- インデックスがアクセサーの際にパフォーマンスが低下する問題を修正しました。

  - 例えば、以下のような条件を含むクエリーで起こります。

    - `accessor @ query`

    - `accessor == query`

- バッファーが十分に大きい時に、検索結果の推定サイズがオーバーフローする問題を修正しました。 [PGroonga#GitHub#115][Albert Songさんの報告]

- test(1)のポータビリティを改善しました。（おばたさんがパッチ提供）

- 不足しているツールを追加

  - 前のバージョンに `index-column-diff-all.sh` と `object-inspect-all.sh` がバンドルされていなかったためです。

### 感謝

- Albert Songさん

- おばたさん

## 9.0.9リリース - 2019-10-30

注釈

今回のバージョンからパフォーマンスが低下しているかもしれません。もし、以前よりパフォーマンスが低下していたら、是非、再現手順を報告してほしいです。

### 改良

- [ログ] 応答の送信時間をクエリーログに出力するように改良しました。

- [status] `status` コマンドの応答に現在のジョブ数を追加しました。

- [groonga-httpd] `$request_time` をサポートしました。

  - 以前のバージョンでは、 `log_format` ディレクティブに `$request_time` を指定しても、`$request_time` の値は常に0でした。

  - 今回のバージョンから、 `$request_time` を指定した場合、 groonga-httpd は正しい時間を出力します。

- [groonga-httpd] `$request_time` の設定方法をドキュメントに追加しました。

- Ubuntu 19.10(Eoan Ermine)をサポートしました。

- CentOS 8をサポートしました。(実験的)

  - CentOS 8向けのパッケージは開発用のパッケージが不足しているため、一部の機能が使えません。(例えば、 `TokenMecab` が使えなかったり、JSON文字列からint32のベクターへのキャストが出来なかったりします。)

- [tools] `index_column_diff` コマンドを簡単に実行するスクリプトを追加しました。

  - このスクリプトの名前は、index-column-diff-all.shです。

  - このスクリプトは、Groongaのデータベースからインデックスカラムを抽出し、抽出したインデックスカラムに対して `index_column_diff` を実行します。

- [tools] `object_inspect` コマンドを全てのオブジェクトに対して実行するスクリプトを追加しました。

  - このスクリプトの名前は、object-inspect-all.shです。

### 修正

- between の最初の引数として値を指定すると、Groongaがクラッシュする問題を修正しました。[GitHub#1045][yagisumiさんの報告]

### 感謝

- yagisumiさん

## 9.0.8リリース - 2019-09-27

### 改良

- [log_reopen] 2つ以上のワーカーで `groonga-httpd` を使用する場合の補足説明を追記しました。

- 作成中のインデックスを無視するように改良しました。

  - インデックス構築中であっても、正しい検索結果を取得できます。

  - ただし、この場合、Groongaは検索にインデックスを使用しないため、検索は遅くなります。

- [sub_filter] 対象のカラムのインデックスが作成中か、または、インデックスが無い時に `sub_filter` がシーケンシャルサーチを実行する機能を追加しました。

  - 以前のバージョンでは、上記の状態の場合、 `sub_filter` はエラーになりました。

  - 今回のバージョンから、 上記の状態でも `sub_filter` は検索結果を返します。

  - ただし、上記の状態の場合、 `sub_filter` は、シーケンシャルサーチで実行されるため遅いです。

- [CentOS] CentOS 6の32-bitパッケージのサポートをやめました。

### 修正

- [logical_range_filter] レコードが十分にあるとき、かつフィルター条件にマッチしないレコードが推定値を超えた時に、同じオブジェクトを2回閉じるという例外が発生する問題を修正しました。

## 9.0.7リリース - 2019-08-29

### 改良

- [httpd] バンドルしているnginxのバージョンを1.17.3に更新しました。

  - CVE-2019-9511、CVE-2019-9513、CVE-2019-9516のセキュリティの修正が含まれています。

### 修正

- ポスティングリストが巨大になった時にGroongaがクラッシュする問題を修正しました。

  - ただし、このバグは、一般的なデータでは殆ど発生しません。ポスティングリストは、一般的なデータでは、そこまで大きくならないためです。

- 動的カラムのステージに `initial` を指定し、インデックスを使用した検索をすると空の結果を返す問題を修正しました。 [GitHub#683]

- configure時にlibeditがインストールされているにもかかわらず、検知しない問題を修正しました。 [GitHub#1030][yuさんがパッチ提供]

- `--slices` と `--sort_keys` オプション使用時に `--offset` と `--limit` オプションが動作しない問題を修正しました。 [clear-code/redmine_full_text_search#70][a9zawaさんの報告]

- `select` コマンドの結果が巨大な時、検索結果が空になる問題を修正しました。[groonga-dev,04770][Yutaro Shimamuraさんの報告]

- 前方一致検索や後方一致検索時に適切なインデックスを使わない問題を修正しました。[GitHub#1007, PGroonga#GitHub#96][oknjさんの報告]

### 感謝

- oknjさん

- Yutaro Shimamuraさん

- yuさん

- a9zawaさん

## 9.0.6リリース - 2019-08-05

### 改良

- Debian 10 (buster)をサポートしました。

### 修正

- [select] 検索エスカレーションが起こった際に検索がエラーになるバグを修正しました。

- [select] ネストされた等価演算を使った際に、誤った検索結果を返すことがあるバグを修正しました。

- [geo_distance_location_rectangle] `load` のフォーマットが誤っている例を修正しました。 [GitHub#1023] [yagisumiさんがパッチ提供]

- [マイクロブログ検索システムの作成] 検索結果が誤っている例を修正しました。[GitHub#1024][yagisumiさんがパッチ提供]

### 感謝

- yagisumiさん

## 9.0.5リリース - 2019-07-30

警告

このリリースには影響の大きい不具合があることがわかりました。`select` コマンドが誤った結果を返します。この問題を修正し、9.0.6をリリースする予定です。Groonga 9.0.5は使わず、後日リリースされる9.0.6を使ってください。問題の詳細については https://groonga.org/ja/blog/2019/07/30/groonga-9.0.5.html で解説しています。

### 改良

- [logical_range_filter] 検索対象のシャードが十分に大きい時にのみ最適化を適用するように改良しました。

  - この機能は、ソートキーが同じ時にオフセット間で検索結果が重複するのを減らします。

  - 十分に大きいのしきい値はデフォルトで10000レコードです。

- [ノーマライザー] `NormalizerNFKC100` に新しいオプション `unify_to_katakana` を追加しました。

  - このオプションは、平仮名を片仮名にノーマライズします。

  - 例えば、 `ゔぁゔぃゔゔぇゔぉ` を `ヴァヴィヴヴェヴォ` にノーマライズします。

- [select] slicesパラメーターでdrilldownsをサポートしました。

- [select] slicesパラメーターでcolumnsをサポートしました。

- [select] initialステージ内でslicesパラメーターが `_score` を参照できるよう改良しました。

- [highlight_html], [snippet_html] slicesパラメータ指定時に、slices実行前の式からもキーワードを抽出するように改良しました。

- slicesパラメータ指定時に、slices実行前の式からもスコアーを収集するように改良しました。

- ポスティングリストにポスティングを追加する際に自動的にスコアーを1増やすのをやめました。

  - `grn_ii_posting_add` は、この変更によって後方互換性がなくなりました。互換性を保つには、呼び出し側でスコアーを増やす必要があります。

- `XXX.YYY.ZZZ == AAA` のようなネストされた等価演算のインデックス検索をサポートしました。

- ハッシュテーブル使用時にハッシュの再構築の間隔を少なくしました。

  - この昨日によって、結果出力のパフォーマンスが改善します。

- クエリーログにプレフィックスを追加できるようになりました。

  - どの条件のフィルターなのかわかりやすくなります。

- Apache Arrow 1.0.0 をサポートしました。

  - ただし、このバージョンはまだ、リリースされていません。

- Amazon Linux 2 をサポートしました。

### 修正

- `"[1, 2, 3]"` のようなJSONのベクター値がインデックスされないバグを修正しました。

- `table_create` のテストのパラメーター名が誤っていたバグを修正しました。[GitHub#1000][yagisumiさんがパッチ提供]

- `command_version=3` でdrilldownコマンドが実行された際に、ドリルダウンのラベルが空になるバグを修正しました。[GitHub#1001][yagisumiさんの報告]

- MinGWでWindows版のパッケージのビルドが失敗するバグを修正しました。

- MinGWのWindows版パッケージにCOPYINGがインストールされないバグを修正しました。

- ハイライト対象として、クエリーにテキスト以外を指定した際に、キーワードがハイライトされないバグを修正しました。

- [object_inspect] のMessagePack形式の出力が壊れるバグを修正しました。[GitHub#1009][yagisumiさんの報告]

- `index_column_diff` のMessagePack形式の出力が壊れるバグを修正しました。[GitHub#1009][yagisumiさんの報告]

- [suggest] のMessagePack形式の出力が壊れるバグを修正しました。[GitHub#1011][yagisumiさんの報告]

- パトリシアトライのテーブルの検索時などにreallocのサイズが十分に確保されないバグを修正しました。[島津製作所さんの報告]

  - Groongaはこのバグでクラッシュする可能性があります。

- `groonga-release` version 1.5.0より前から1.5.0-1へアップデートした際に `groonga.repo` が削除されるバグを修正しました。[groonga-talk:429][Josep Sanzさんの報告]

### 感謝

- yagisumiさん

- 島津製作所さん

- Josep Sanzさん

## 9.0.4リリース - 2019-06-29

### 改良

- 配列リテラルの複数要素をサポートしました。

- ベクターの等価演算をサポートしました。

- [logical_range_filter] 出力するクエリーログを追加しました。

  - `logical_range_filter` コマンドが、以下のタイミングでログを出力するようになります。

    - `logical_range_filter` によるフィルター後

    - `logical_range_filter` によるソート後

    - 動的カラム適用後

    - 結果出力後

  - この機能によって、このコマンドがどこまで完了したかを見ることができます。

- [トークナイザー] `TokenPattern` の説明をドキュメントに追加しました。

- [トークナイザー] `TokenTable` の説明をドキュメントに追加しました。

- [トークナイザー] `TokenNgram` の説明をドキュメントに追加しました。

- [grndb] groonga.logへの操作ログの出力を追加しました。

  - `grndb` コマンドが実行結果と実行過程を出力するようになります。

- [grndb] 空のファイルのチェックをサポートしました。

  - この機能によって、空のファイルが存在するかどうかをチェックできます。

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

  - 検査の範囲を指定できます。

- [grndb] 新しいオプション `--since` についてのドキュメントを追加しました。

- RapidJSONをバンドルしました。

  - 部分的にGroongaのJSONパーサーとしてRapidJSONを使うことができます。(この機能はまだ部分的です。)

  - これを使うことでより厳格なJSONのパースができます。

- JSON文字列からint32のベクターへのキャストをサポートしました。

  - この機能は、RapidJSONが必要です。

- [query] `default_operator` を追加しました。

  - "keyword1 keyword2"時の演算子をカスタマイズできます。

  - デフォルトでは、"keyword1 keyword2"はAND演算です。

  - "keyword1 keyword2"の演算子をAND以外に変更できます。

### 修正

- [optimizer] 複数のfilter条件と `xxx.yyy=="keyword"` のような条件を指定した際にエラーが発生するバグを修正しました。

- GroongaのWindows用のパッケージ(VC++版)に不足していたライセンスファイルを追加しました。

- GroongaのWindows用のパッケージ(VC++版)UCRTランタイムを追加しました。

- [ウィンドウ関数] メモリリークを修正しました。

  - これは、複数のウインドウに対してソートキーを適用した際に発生します。 [Takashi Hashidaさんがパッチ提供]

### 感謝

- Takashi Hashidaさん

## 9.0.3リリース - 2019-05-29

### 改良

- [select] より多くのクエリーログを追加しました。

  - `select` コマンドが、以下のタイミングでログを出力するようになります。

    - ドリルダウンによるソート後

    - ドリルダウンによるフィルター後

  - この機能によって、このコマンドがどこまで完了したかを見ることができます。

- [logical_select] より多くのクエリーログを追加しました。

  - `logical_select` コマンドが、以下のタイミングでログを出力するようになります。

    - 動的カラム作成後

    - ドリルダウンによるグループ化後

    - ドリルダウンによるソート後

    - ドリルダウンによるフィルター後

    - `logical_select` によるソート後

  - この機能によって、このコマンドがどこまで完了したかを見ることができます。

- [logical_select] `limit` オプションを使用したときのソートのパフォーマンスを少し改善しました。

- [index_column_diff] パフォーマンスを改善しました。

  - このコマンドの実行速度を大幅に短くしました。

- [index_column_diff] 無効な参照を無視するように改良しました。

- [index_column_diff] ベクター要素の重複に対応しました。

- [Normalizers] Unicode 12.1 の NFKC（Normalization Form Compatibility Composition）をベースにしたノーマライザー `NormalizerNFKC121` を追加しました。

- [TokenFilters] Unicode 12.1 の NFKC（Normalization Form Compatibility Composition）をベースにしたトークンフィルター `NormalizerNFKC121` を追加しました。

- [grndb] 新しいオプション `--log-flags` を追加しました。

  - groonga実行ファイルと同様、ログに出力する項目を指定できます。

  - サポートされているログフラグについては、[groonga 実行ファイル] を参照してください。

- [snippet_html] 検索にマッチしない時の戻り値を変更する新しいオプションを追加しました。

- [plugin_unregister] Windowsのフルパスをサポートしました。

- 複数行のログメッセージをサポートしました。

  - この機能によって、複数行に渡るログメッセージが見やすくなります。

- インデックスを使って検索した際、キーをGroongaのログに出力するようにしました。

- [match_columnsパラメータ] インデックスの重みのドキュメントを追加しました。

- [logical_range_filter] `order` パラメータの説明を追加しました。

- [object_inspect] 新しい統計 `INDEX_COLUMN_VALUE_STATISTICS_NEXT_PHYSICAL_SEGMENT_ID` と `INDEX_COLUMN_VALUE_STATISTICS_N_PHYSICAL_SEGMENTS` の説明を追加しました。

- Ubuntu 14.04 のサポートをやめました。

### 修正

- [index_column_diff] `remains` を多く報告するバグを修正しました。

- `--without-onigmo` オプションを使った際にビルドエラーになるバグを修正しました。[GitHub#951] [Tomohiro KATOさんが報告]

- "CVE: 2019-11675"の脆弱性を修正しました。[Wolfgang Hotwagnerさんが報告]

- Windows版のGroongaにて、拡張パスプレフィックス `\\?\` を削除しました。[GitHub#958] [yagisumiさんが報告]

  - この拡張プレフィックスは、プラグインを正確に見つけられないというバグを引き起こします。

### 感謝

- Tomohiro KATOさん

- Wolfgang Hotwagnerさん

- yagisumiさん

## 9.0.2リリース - 2019-04-29

このリリースからVC++で作成したWindows版パッケージを提供します。

今までどおり、MinGWで作成したWindows版パッケージも提供しますが、近いうちにMinGWで作ったパッケージの代わりにVC++で作ったパッケージを提供する予定です。

### 改良

- [column_create] 新しいフラグ `INDEX_LARGE` を追加しました。

  - このフラグによって、デフォルトの2倍の領域を持つインデックスカラムを作成できます。

  - ただ、メモリ使用量も2倍となることに注意して下さい。

  - このフラグは、インデックス対象のデータが大きい時に有用です。

  - 大きいデータとは、大量のレコード（通常は少なくとも1000万レコード以上）があり、少なくとも次のうちの1つ以上の特徴があります。

    - インデックス対象が複数のカラム

    - インデックステーブルにトークナイザーが付いている

- [object_inspect] セグメントの新しい統計値 `next_physical_segment_id` と `max_n_physical_segments` を追加しました。

  - この情報で、インデックスカラムの領域の使用量とインデックスカラムの領域の最大値を確認できます。

- [logical_select] シャードをまたがったウィンドウ関数をサポートしました。

- [logical_range_filter] シャードをまたがったウインドウ関数をサポートしました。

- [logical_count] シャードをまたがったウインドウ関数をサポートしました。

- このリリースからVC++で作成したWindows版パッケージを提供するようにしました。

- [io_flush] 新しいオプション `--recursive dependent` を追加しました。

  - 指定した書き出し対象オブジェクトとその子オブジェクトすべて、参照先のテーブル、インデックスが張られているカラムがある場合、対応するインデックスカラムとそのインデックスカラムのテーブルを書き出し対象オブジェクトにできます。

### 修正

- 一部の環境でコンパイルエラー "unknown type name 'bool'" が発生する問題を修正しました。

- mrubyを経由して実行するコマンド(例えば、 `logical_select`、 `logical_range_filter`、 `logical_count` 等)で、Int32を超える数を正しく出力できない問題を修正しました。[GitHub#936] [HashidaTKSさんがパッチ提供]

### 感謝

- HashidaTKSさん

## 9.0.1リリース - 2019-03-29

### 改良

- ベクターの値にnullが使えるようになりました。

  - select ... --columns[vector].flags COLUMN_VECTOR --columns[vector].value "null" のように使用できます。

- [dump] ドキュメントを英語に翻訳しました。

- 無効なインデックスのチェックとログへの記録を強化しました。インデックス関連のバグを発見するのに役立ちます。

- 8.0.6リリース - 2018-08-29 の `GRN_TABLE_SELECT_ENOUGH_FILTERED_RATIO` の説明を改善しました。

- [select] 新しい引数 `--load_table` 、`--load_columns` 、 `--load_values` を追加しました。

  - `select` の結果を `--load_table` で指定したテーブルへ格納できます。

  - `--load_values` オプションは、`select` の結果のカラムを指定します。

  - `--load_columns` オプションは、`--load_table` で指定したテーブルのカラムを指定します。

  - このようにして、`--load_values` で指定したカラムの値を、 `--load_columns` で指定したカラムへ格納できます。

- [select] 新しい引数 `--load_table` 、`--load_columns` 、 `--load_values` を追加しました。

- [load] ロード先のテーブルをクエリーログに表示するようにしました。

  - 以下のように、ロード先のテーブル名は `[]` 内の文字列として表示します　。

  - `:000000000000000 load(3): [LoadedLogs][3]`

- 以下のAPIを追加しました。

  - `grn_ii_get_flags()`

  - `grn_index_column_diff()`

  - `grn_memory_get_usage()`

- 壊れたインデックスをチェックするためのコマンド `index_column_diff` を追加しました。コマンド実行の進捗を記録したい場合は、ログレベルをdebugに設定してください。

### 修正

- [snippet_html] 一致しない場合、空のベクターを返すよう変更しました。

  - そのような場合、 `null` の代わりに空のベクター `[]` が返されます。

- スレッドカウントがオーバフローする可能性についての警告を修正しました。実運用では、膨大な数のスレッドが使用されていないため、ユーザーに影響はありません。[GitHub#904]

- maxOSでのビルドエラーを修正しました。 [GitHub#909] [shiro615さんが報告]

- ストップワードの処理のバグを修正しました。

  - このバグは、クエリーの最初のトークンをストップワードとして設定すると発生します。

  - このバグが発生した場合、検索クエリーはヒットしません。

- [全体設定] `grn_lock_set_timeout` のパラメーター名の誤字を修正しました。

- インデックスの破損によって、削除されたレコードがマッチするバグを修正しました。

  - 大量のレコードを追加または、削除した時に発生することがあります。

- `logical_range_filter` がレコードを返さない場合のメモリリークを修正しました。[GitHub#911] [HashidaTKSさんがパッチ提供]

- ロードしているデータが正しくノーマライズされないことによってクエリーにマッチしないバグを修正しました。[PGroonga#GitHub#93, GitHub#912,GitHub#913] [kamicupさんとdodaisukeさんが報告]

  - このバグは、カタカナの後ろに空白のあるデータをロードし、ノーマライザーに `unify_kana` オプションが使用された時に発生します。

- インデックスの更新中にインデックスが破損するバグを修正しました。

  - 長期間、大量のレコードの追加、削除を繰り返した時に発生することがあります。

- インデックス更新時に十分な作業領域を確保できずにクラッシュするバクを修正しました。

### 感謝

- shiro615さん

- HashidaTKSさん

- kamicupさん

- dodaisukeさん

## 9.0.0リリース - 2019-02-09

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

### 改良

- [トークナイザー] 新しいトークナイザー `TokenPattern` を追加しました。

  - 正規表現を使ってトークンを抽出できます。

    - このトークナイザーは正規表現にマッチしたトークンのみを抽出します。

  - 正規表現のパターンは複数指定できます。

- [トークナイザー] 新しいトークナイザー `TokenTable` を追加しました。

  - 既存のテーブルのカラムの値を使ってトークンを抽出できます。

- [dump] バイナリデータのダンプに対応しました。

- [select] インデックスカラムに対する類似文書検索をサポートしました。

  - マルチカラムインデックスを使用している場合、この機能を使って、全てのソースカラムに対して類似文書検索ができます。

- [ノーマライザー] `NormalizerNFKC100` に新しいオプション `remove_blank` を追加しました。

  - このオプションは空白を取り除きます。

- [groonga 実行ファイル] ログ内のThreadIDの表示を改善しました。

  - Windows版では、ProcessIDとThreadIDを混同しやすかったので、どちらがThreadIDでどちらがProcessIDかを明確にしました。

## 8.1.1リリース - 2019-01-29

### 改良

- [logical_select] 新しい引数 `--load_table` 、`--load_columns` 、 `--load_values` を追加しました。

  - `logical_select` の結果を `--load_table` で指定したテーブルへ格納できます。

  - `--load_values` オプションは、`logical_select` の結果のカラムを指定します。

  - `--load_columns` オプションは、`--load_table` で指定したテーブルのカラムを指定します。

  - このようにして、`--load_values` で指定したカラムの値を、 `--load_columns` で指定したカラムへ格納できます。

- インデックスの更新エラー時のログを改善しました。

  - ログに、より詳細な情報を追加しました。

    - 例えば、ポスティングリストのマージに失敗した時にマージ元のバッファーとチャンクを出力します。

    - また、バッファー確保のエラーが発生した時は、バッファーの空き領域と要求サイズをログに出力します。

- [groonga 実行ファイル] 新しいオプション `--log-flags` を追加しました。

  - Groongaのログに出力する項目を指定できます。

  - 以下のような項目を出力できます。

    - タイムスタンプ

    - ログメッセージ

    - ロケーション(ログが出力された場所)

    - プロセスID

    - スレッドID

  - 以下のように接頭辞を指定できます。

    - `+`

      - この接頭辞は、 "フラグを追加する"という意味です。

    - `-`

      - この接頭辞は、"フラグを削除する"という意味です。

    - 接頭辞無しは、"存在しているフラグを置き換える"という意味です。

  - 具体的には、以下のようにフラグ指定できます。

    - `none`

      - ログに何も出力しません。

    - `time`

      - ログにタイムスタンプを出力します。

    - `message`

      - ログにメッセージを出力します。

    - `location`

      - ログの出力場所(ファイル名、行数、関数名)とプロセスIDを出力します。

    - `process_id`

      - ログにプロセスIDを出力します。

    - `pid`

      - このフラグは、 `process_id` のエイリアスです。

    - `thread_id`

      - ログにスレッドIDを出力します。

    - `all`

      - このフラグは、 `none` と `default` 以外の全てのフラグを指定します。

    - `default`

      - ログに、タイムスタンプとログメッセージを出力します。

  - `|` を使って、複数のフラグを指定することもできます。

### 修正

- インデックスの更新エラー発生時にメモリリークする問題を修正しました。

- [ノーマライザー] ステートレスなノーマライザーとステートフルなノーマライザーを同時に使用した時に、それらが誤った結果を返すバグを修正しました。

  > - ステートレスなノーマライザーとは以下です。

  >   - `unify_kana`

  >   - `unify_kana_case`

  >   - `unify_kana_voiced_sound_mark`

  >   - `unify_hyphen`

  >   - `unify_prolonged_sound_mark`

  >   - `unify_hyphen_and_prolonged_sound_mark`

  >   - `unify_middle_dot`

  > - ステートフルなノーマライザーとは以下です。

  >   - `unify_katakana_v_sounds`

  >   - `unify_katakana_bu_sound`

  >   - `unify_to_romaji`

## 8.1.0リリース - 2018-12-29

### 改良

- [httpd] バンドルしているnginxのバージョンを1.15.8に更新しました。

### 修正

- `io_flush` コマンド実行後に、DBに対するアンロックが常にフラッシュの実行後になってしまうバグを修正しました。

- 参照先を持たないレコードを持つテーブルに対して `reindex` コマンドを実行した際に、 `reindex` コマンドが終了しないバグを修正しました。

## 8.0.9リリース - 2018-11-29

### 改良

- [トークナイザー] トークナイザーの作成に失敗した際のエラーメッセージにトークナイザーの名前を出力するよう改良。

- [トークナイザー][TokenDelimit] トークンの区切り文字のカスタマイズをサポートしました。

  - 空白以外のトークンを区切り文字に使えます。

- [トークナイザー][TokenDelimit] 新しいオプション `pattern` を追加しました。

  - このオプションにより、区切り文字にに正規表現を指定できます。

- [トークナイザー] 各トークンの情報に `force_prefix_search` の値を追加しました。

  - "force_prefix" は後方互換のため残しています。

- [トークンフィルター] ビルトインのトークンフィルタ `TokenFilterNFKC100` を追加しました。

  - NormalizerNFKC100のように `unify_kana` オプションで、カタカナをひらがなへ変換できます。

- [トークンフィルター][TokenFilterStem] 新しオプション `algorithm` を追加しました。

  - このオプションによって、英語以外の言語(フランス語、スペイン語、ポルトガル語、イタリア語、ルーマニア語、ドイツ語、オランダ語、スウェーデン語、ノルウェー語、デンマーク語、ロシア語、フィンランド語)をステミングできます。

- [トークンフィルター][TokenFilterStopWord] 新しいオプション `column` を追加しました

  - このオプションによって、is_stop_word以外のカラムをスットプワードに指定できます。

- [dump] トークンフィルターのオプションの出力をサポートしました。

  - `TokenNgram` や `TokenMecab` 等のようなオプションを持つトークナイザーを指定した場合、それらのオプションも `table_list` コマンドで出力できます。

- [truncate] トークンフィルターのオプションを持ったテーブルをサポートしました。

  - `TokenFilterStem` や `TokenStopWord` 等のようなオプションを持つトークナイザーを持つテーブルでも `truncate` できます。

- [schema] トークンフィルターのオプションの出力をサポートしました。

- [ノーマライザー] `NormalizerNFKC100` に新しいオプション `unify_to_romaji` を追加しました。

  - このオプションによって、ひらがなとカタカナをローマ字に正規化できます。

- [query-log][show-condition] "func() > 0"をサポートしました。

- [Windows] アンマップ前のフラッシュを確実にするよう改善しました。

- ファイル入力のエラーメッセージを改善しました。

- [httpd] バンドルしているnginxのバージョンを1.15.7に更新しました。

  - CVE-2018-16843とCVE-2018-16844のセキュリティの修正が含まれています。

### 修正

- ウインドウ関数を評価する際にメモリリークする問題を修正しました。

- [groonga-httpd] ログの内容が混在することがあるバグを修正しました。

- output_columnsのスライスのエラーが発生した際に、無効なJSONが生成されるバグを修正しました。

- ネストして参照されているベクターカラムの値を取得する際にメモリリークする問題を修正しました。

- インデックス破損を警告するログを出力する際にクラッシュするバグを修正しました。

- 式の評価で一時的なベクターが再利用された時にクラッシュするバグを修正しました。

  - 例えば、以下のようにベクターを使った式を評価する時にクラッシュします。

  `_score = _score + (vector_size(categories) > 0)`

- deleteコマンドで削除したベクターカラムの値がヒットするバグを修正しました。[dodaisukeさんの報告]

### 感謝

- dodaisukeさん

## 8.0.8リリース - 2018-10-29

### 改良

- [table_list] デフォルトトークナイザーのオプションをサポートしました。

  - `TokenNgram` や `TokenMecab` 等のようなオプションを持つトークナイザーを指定した場合、それらのオプションも `table_list` コマンドで出力できます。

- [select] `record @ 'query'` を使ったシーケンシャルマッチでノーマライザーのオプションをサポートしました。

- [truncate] トークナイザーのオプションを持ったテーブルをサポートしました。

  - `TokenNgram` や `TokenMecab` 等のようなオプションを持つトークナイザーを持つテーブルでも `truncate` できます。

- [トークナイザー][TokenMecab] `TokenMecab` に `target_class` オプションを追加しました。

  - このオプションは、指定した品詞のトークンを検索します。例えば、名詞のみを検索することができます。

  - このオプションは、以下のようにサブクラスを指定することや、 `+` や `-` を使って、特定の品詞を追加または除外することもできます。したがって、以下のように代名詞を除外して検索することもできます。

    `'TokenMecab("target_class", "-名詞/代名詞", "target_class", "+")'`

- [io_flush] `io_flush` 中のデータベースのロックをサポートしました。

  - `io_flush` 実行中に `io_flush` 対象のテーブルを削除するとGroongaがクラッシュする問題があったためです。

- [cast_loose] 新しい関数 `cast_loose()` を追加しました。

  - この関数は、指定した型へキャストします。もし、指定した値がキャストできない場合、値は、指定したデフォルト値になります。

- 条件式の評価順序の最適化を追加しました。(実験的)

  - 以下のように環境変数を設定することでこの機能を有効にできます。

    `GRN_EXPR_OPTIMIZE=yes`

- インデックス検索可能な正規表現に `(?-mix:XXX)` 記法をサポートしました。 [groonga-dev,04683][ Masatoshi SEKIさんの報告]

  - `(?-mix:XXX)` は XXX と同じ扱いです。

- [httpd] バンドルしているnginxのバージョンを1.15.5に更新しました。

- Ubuntu 18.10 (Cosmic Cuttlefish)をサポートしました。

### 修正

- Groonga GQTP サーバーが新しい接続を受け付けなくなることがあるバグを修正しました。[groonga-dev,04688][Yutaro Shimamuraさんの報告]

  - quitを使わずにクライアントプロセスを中断した時に発生します。

### 感謝

- Masatoshi SEKIさん

- Yutaro Shimamuraさん

## 8.0.7リリース - 2018-09-29

### 改良

- [トークナイザー][TokenMecab] Mecabのメタデータの出力をサポートしました。

  - `TokenMecab` に `include_class` オプションを追加しました。

    このオプションは、Mecabのメタデータの `class` と `subclass` を出力します。

  - `TokenMecab` に `include_reading` オプションを追加しました。

    このオプションは、Mecabのメタデータの `reading` を出力します。

  - `TokenMecab` に `include_form` オプションを追加しました。

    このオプションは、Mecabのメタデータの `inflected_type` と `inflected_form` 、 `base_form` を出力します。

  - `TokenMecab` に `use_reading` オプションを追加しました。

    このオプションは、読みがなによる検索をサポートします。

    このオプションは、読みがなを使った検索をするため、表記ゆれの対策として有用です。

- [plugin] 複数のディレクトリからプラグインを取得できるようになりました。

  `GRN_PLUGINS_PATH` に複数のディレクトリを指定できます。Windowsの場合は、":"でWindows以外では、";"で区切ります。

  `GRN_PLUGINS_PATH` は、 `GRN_PLUGINS_DIR` より優先度が高いです。現状、このオプションはWindowsではサポートされていません。

- [トークナイザー][TokenNgram] `TokenNgram` に `unify_alphabet` オプションを追加しました。

  `unify_alphabet` を `false` として使うと、 `TokenNgram` はASCII文字のトークナイズ方法にバイグラムを使います。

- [トークナイザー][TokenNgram] `TokenNgram` に `unify_symbol` オプションを追加しました。

  `TokenNgram("unify_symbol", false)` は、 `TokenBigramSplitSymbol` と同じ動作です。

- [トークナイザー][TokenNgram] `TokenNgram` に `unify_digit` オプションを追加しました。

  `unify_digit` を `false` として使うと、 `TokenNgram` は数字のトークナイズ方法にバイグラムを使います。

- [httpd] バンドルしているnginxのバージョンを1.15.4に更新しました。

### 修正

- いくつかのケースでの誤ったスコア計算を修正しました。

  - ブール値に数値を加算、乗算または除算するときに発生します。

  - `！=` や `==` を使ってスカラーとベクトルの列を比較するときに発生します。

## 8.0.6リリース - 2018-08-29

### 改良

- [トークナイザー][TokenMecab] `chunked_tokenize` と `chunk_size_threshold` の両オプションに対応しました。

- [optimizer] query family expressionの推定に対応しました。`column @ query` や `column @~ pattern` のようなquery family expressionについて、より効果的な実行計画を立てられます。

- [optimizer] オプティマイザをプラグインから組み込みの機能に変更し、初期状態で無効としました。環境変数を `GRN_EXPR_OPTIMIZE=yes` と定義するか、従来通りに `expression_rewriters` テーブルを使う事で機能を有効化できます。

- 充分に絞り込み済みの場合において、初期状態でシーケンシャルサーチを行うようにしました。現在の結果が充分に少数である場合、シーケンシャルサーチはインデックス検索よりも高速です。現在の結果がテーブル内の全レコードの1%で1000件未満の場合、インデックス検索可能な場合であってもシーケンシャルサーチが使われます。

  現在、この最適化は、 `==` と `>` と `<` と `>=` と `<=` を使った検索時に適用されます。

  絞り込みに指定したカラムを持つテーブルのキーが `ShortText` の場合、この最適化を適用するためには、そのテーブルのノーマライザーを `NormalizerAuto` にする必要があります。

  この機能は環境変数で `GRN_TABLE_SELECT_ENOUGH_FILTERED_RATIO=0.0` と設定する事で無効化できます。

- [load] エラーメッセージにテーブル名を含めるようにしました。

- [load] `lock_table` オプションを追加しました。`--lock_table yes` が指定された場合、カラムの更新と `--each` の適用を行っている間、`load` は対象のテーブルをロックします。このオプションは `load` と `delete` の衝突を防ぎますが、読み込みの性能を低下させるでしょう。

- [vector_find] サポートされていないモードでクラッシュしないようにしました。

### 修正

- [index] `HASH_KEY` を伴ったテキストのベクターに対するオフラインでのインデックス構築に関して、誤ったセクションIDを持つインデックスが構築されてしまうバグを修正しました。

- `--match_columns 'index[0] || index[9]'` が誤ったセクションを使用してしまう問題を修正しました。

- [highlighter] 語彙表がハッシュテーブルで、且つキーワードがN-gramのNよりも少ない文字数の場合に、誤ったハイライトが行われていた問題を修正しました。

- [mruby] 本当のエラーが隠されていた問題を修正しました。mrubyは引数無しで投げられたエラーの伝搬に対応していません。mruby/mruby#290

- [トークナイザー][TokenNgram loose]: クエリが曖昧な種類のみであった場合に検索結果が見つからない問題を修正しました。語彙表を伴っての `highlight_html()` も同様に壊れていました。

- テキストから数値への変換において、後続するゴミ部分が無視されていた問題を修正しました。 "0garbage" は変換エラーになります。

- `reference_column >= 'key_value'` に当てはまる場合の最適化の問題を修正しました。

## 8.0.5リリース - 2018-07-29

### 改良

- [スクリプト構文] 類似文書検索の補足説明とその日本語訳を追加しました。 [GitHub groonga/GitHub#858] [堀本さんがパッチ提供]

- [time_classify_day_of_week] 新しい関数 `time_classify_day_of_week()` を追加しました。

- `-fstack-protector` で警告を抑制するようにしました。（OBATA Akioさんが提案）

- 新しいAPI `time_format_iso8601()` を追加しました。

- `grn_raw_string` 構造体を公開。

- 新しいAPI: `grn_obj_clear_option_values()` を追加しました。永続的なデータベースのremoveと一時的なデータベースのcloseの際にオプションの値を消去できます。

- [log] `[ii][update][one]` のエラーメッセージにインデックスカラム名を出力するようにしました。

- [httpd] バンドルしているnginxのバージョンを1.15.2に更新しました。

- [Ubuntu] Ubuntu 17.10 (Artful Aardvark）のサポートをやめました。2018年7月19日でサポートが切れた（EOLになった）ためです。

- [Debian GNU/Linux] jessieのサポートをやめました。Debianのセキュリティ＆リリースチームはもはやjessieの更新を提供しません。

### 修正

- POSTでの `/d/load` へのデータ送信が中断された後に誤った結果が返されていたのを修正しました。

- KyTeaに関する間違った関数呼び出しを修正しました。

- [grndb] `--force-truncate` オプションのラベルを追加しました。

- `groonga-normalizer-mysql` のようにプラグインとして提供されているノーマライザーでオプションを使った場合に、データベースを終了するときにクラッシュする問題を修正しました。

- ノーマライザーとトークナイザーのオプションが無視される場合があった問題を修正しました。この問題は同じオブジェクトIDが再利用された場合に発生していました。

## 8.0.4リリース - 2018-06-29

### 改良

- [log] `[ii][update][one]` のエラーメッセージにサブエラーを追加しました。

- 新しいAPI `grn_highlighter_clear_keywords()` を追加しました。

- 新しいpredicate `grn_obj_is_number_family_bulk()` を追加しました。

- 新しいAPI `grn_plugin_proc_get_value_mode()` を追加しました。

- [vector_find] 新しい関数 `vector_find()` を追加しました。

- msgpackでのmemcpyの警告を抑制しました。

- mrubyを1.0.0から1.4.1に更新しました。

- [doc][grn_obj] `grn_obj_is_index_column()` のAPIリファレンスを追加しました。

- [windows] printfフォーマットの警告を抑制しました。

- [windows] msgpackによる警告を抑制しました。

- [grn_obj][Plugin] エンコーディングコンバーターを追加しました。ルール:

  - grn_ctx::errbuf: grn_encoding

  - grn_logger_put: grn_encoding

  - mruby: UTF-8

  - path: locale

- [mrb] `LocaleOutput` を追加しました。

- [windows] イメージのパスのgrn_encodingへの変換をサポートしました。

- [トークナイザー][TokenMecab] エラーメッセージのエンコーディングを変換するようにしました。

- [window_sum] 対象カラムとしての動的カラムをサポートしました。

- [doc][grn_obj] `grn_obj_is_vector_column()` のAPIリファレンスを追加しました。

- [column_create] より多くのバリデーションを追加しました。

  - 1: ベクターカラムの全文検索インデックスは `WITH_SECTION` フラグが必要です。（ただし、 `WITH_POSITION` あり、 `WITH_SECTION` なしのTokenDelmitは許容されます。これはタグ検索に便利なパターンです。)

  - 2: ベクターカラムの全文検索インデックスはマルチカラムインデックスであってはいけません。詳細: groonga/groonga

- [grndb] 実装が不十分だったため、ログのチェックを一時的に無効にしました

### 修正

- [sub_filter] 十分にフィルターされたケースで、スコアが多すぎる問題を修正

- KyTeaがインストールされているとビルドに失敗する問題を修正しました。

- [grndb] 出力チャネルを修正しました。

- [query-log][show-condition] クラッシュするバグを修正しました（まだ残っている可能性があります）。

- [highlighter][lexicon] ハイライトされないバグを修正しました。キーワードの長さがN未満（N-gramのN。多くの場合はBigramなので2未満）の場合、キーワードがハイライトされていませんでした。

- [windows] base path検出時の問題を修正しました。システムロケールのDLLパスが、CP932での「U+8868 CJK UNIFIED IDEOGRAPH-8868」のように0x5c （ASCIIでの `\` )を含む場合に問題がありました。

- [トークナイザー][TokenNgram] 最初の文字の長さの誤りを修正しました。この問題は、「U+3231 PARENTHESIZED IDEOGRAPH STOCK」のような「PARENTHESIZED IDEOGRAPH」文字で起きていました。

## 8.0.3リリース - 2018-05-29

### 改良

- [highlight_html] `NormalizerNFKC100` または `TokenNgram` を使って検索した結果のハイライトをサポートしました。

- [トークナイザー] `TokenNgram` に新しいオプション `report_source_location option` を追加しました。このオプションは、`highlight_html` で語彙表を使ったハイライトをする時に使用します。

- [ノーマライザー] `NormalizerNFKC100` に新しいオプション `unify_middle_dot option` を追加しました。このオプションは、中点を正規化します。`・` の有無や `・` 位置にかかわらず検索できます。

- [ノーマライザー] `NormalizerNFKC100` に新しいオプション `unify_katakana_v_sounds option` を追加しました。このオプションは、`ヴァヴィヴヴェヴォ` を `バビブベボ` へ正規化します。例えば `バイオリン` を `ヴァイオリン` で検索できます。

- [ノーマライザー] `NormalizerNFKC100` に新しいオプション `unify_katakana_bu_sound option` を追加しました。このオプションは、`ヴァヴィヴゥヴェヴォ` を `ブ` に正規化します。例えば、`セーブル` や `セーヴル` を `セーヴェル` で検索できます。

- [sub_filter] 十分にフィルターされたケースでの `sub_filter` の動作を最適化しました。この最適化は、 `sub_filter` 実行前に十分にレコードが絞り込まれているケースで有効になります。

- [groonga-httpd] 全てのワーカのコンテキストアドレスをユニークにしました。コンテキストアドレスは、以下のクエリーログの `#{ID}` です。

  #{TIME_STAMP}|#{MESSAGE}
  #{TIME_STAMP}|#{ID}|>#{QUERY}
  #{TIME_STAMP}|#{ID}|:#{ELAPSED_TIME} #{PROGRESS}
  #{TIME_STAMP}|#{ID}|<#{ELAPSED_TIME} #{RETURN_CODE}

- [delete] 新しいオプション `limit` を追加しました。以下の例のように、削除するレコードの件数を制限できます。`delete --table Users --filter '_key @^ "b"' --limit 4`

- [httpd] バンドルしているnginxのバージョンを1.14.0に更新しました。

### 修正

- [logical_select] 動的カラムをフィルターした時にエラーが発生するとメモリリークする不具合を修正しました。

- [logical_count] 動的カラムの初期化に失敗した際にメモリリークする不具合を修正しました。

- [logical_range_filter] 動的カラムの評価に失敗した際にメモリリークする不具合を修正しました。

- [トークナイザー] `loose_symbol` のように緩いトークナイズをした時に `source_offset` が誤った値になる不具合を修正しました。

- [ノーマライザー] `U+FF21 FULLWIDTH LATIN CAPITAL LETTER A` のような全角ラテン大文字が、`U+0061 LATIN SMALL LETTER A` のようなラテン小文字に正規化されない不具合を修正しました。すでに、 `NormalizerNFKC100` を使用している場合は、インデックスを再生成する必要があります。

## 8.0.2リリース - 2018-04-29

### 改良

- [grndb][--force-truncate] `grndb recover --force-truncate` オプションを指定することで、テーブルにロックが残ったままの状態でも truncate できるようにしました。

- [logical_range_filter] `sort_keys` オプションに対応しました。

- 新しい関数 `time_format()` を追加しました。`Time` 型のカラムの値を時刻表記で出力できます。書式は `strftime` 用の形式を指定できます。

- [トークナイザー] 新しいトークナイザー `TokenNgram` を追加しました。このトークナイザーは、オプションを通じて挙動を動的に変えることができます。対応しているオプションは以下の通りです。

  > - `n` : Ngram の「N」を指定します。例えば trigram の場合は「3」です。

  > - `loose_symbol` : 記号を含む語句について、記号の有無の違いを無視して検索できるようにトークナイズします。例えば「090-1111-2222」という語句は、「09011112222」「090」「1111」「2222」「090-1111-2222」のいずれで検索した場合にも検索結果としてヒットするようになります。

  > - `loose_blank` : 空白を含む語句について、空白の有無の違いを無視して検索できるようにトークナイズします。例えば「090 1111 2222」という語句は、「09011112222」「090」「1111」「2222」「090 1111 2222」のいずれで検索した場合にも検索結果としてヒットするようになります。

  > - `remove_blank` : 空白を含む語句について、空白無しの語句で検索できるようにトークナイズします。例えば「090 1111 2222」という語句は、「09011112222」「090」「1111」「2222」のいずれで検索した場合にも検索結果としてヒットするようになります。空白を含む語句「090 1111 2222」での検索にはヒットしない点にご注意下さい。

- [ノーマライザー] Unicode 10.0 の NFKC（Normalization Form Compatibility Composition）に基づくノーマライザーである "NormalizerNFKC100" を追加しました。

- [ノーマライザー] ノーマライザーの "NormalizerNFKC51" と "NormalizerNFKC100" でのオプション指定に対応しました。ノーマライザーの挙動を動的に変えることができます。対応しているオプションは以下の通りです。

  > - `unify_kana` : 同じ音となる全角ひらがな、全角カタカナ、半角カタカナの文字を同一視します。

  > - `unify_kana_case` : 全角ひらがな、全角カタカナ、半角カタカナで拗音、促音などを表す小さな文字（例：「ぁ」「ゃ」「っ」）を大きな文字と同一視します。

  > - `unify_kana_voiced_sound_mark` : 全角ひらがな、全角カタカナ、半角カタカナで濁点や半濁点の有無を同一視します。

  > - `unify_hyphen` : ハイフンに類する文字すべてをハイフンと同一視します。

  > - `unify_prolonged_sound_mark` : 長音記号に類する文字すべてを長音記号と同一視します。

  > - `unify_hyphen_and_prolonged_sound_mark` : ハイフンに類する文字と長音記号に類する文字のすべてをハイフンと同一視します。

- [dump] トークナイザーとノーマライザーのオプションの出力に対応しました。トークナイザーまたはノーマライザーのオプションを含んだ状態でGroonga 8.0.2およびそれ以降で出力した dump は、Grooga 8.0.1以前のバージョンでは読み込めず、未対応の情報によりエラーとなります。

- [dump] トークナイザーとノーマライザーのオプションの出力に対応しました。トークナイザーまたはノーマライザーのオプションを含んだ状態でGroonga 8.0.2およびそれ以降で出力した schema は、Grooga 8.0.1以前のバージョンでは読み込めず、未対応の情報によりエラーとなります。

- Ubuntu 18.04 (Bionic Beaver)をサポートしました。

### 修正

- スペースのみの検索クエリが意図しないレコードにマッチする不具合を修正しました。[groonga-dev,04609][satouyuzhさんの報告]

- 誤ったスコアラーが使われる場合があった不具合を修正しました。この問題は以下のように複数のスコアラーが使われた時に発生していました： `--match_columns 'title || scorer_tf_at_most(content, 2.0)'`

- 「thread_limit」の変更に時間がかかりすぎる問題を修正しました。

### 感謝

- satouyuzhさん

## 8.0.1リリース - 2018-03-29

### 改良

- [ログ] クエリーログ内で `filter` 条件を表示するようにしました。この機能はデフォルトでは、無効になっています。有効にするためには、環境変数 `GRN_QUERY_LOG_SHOW_CONDITION=yes` を設定します。

- `*.pdb` を `*.dll` と `*.exe` と同じディレクトリにインストールされるようにしました。

- [logical_count] `filtered` ステージの動的カラムをサポートしました。

- [logical_count] [post_filter] フィルタータイミングを新規追加しました。 `filtered` ステージのカラムが生成された後に実行されます。

- [logical_select] [post_filter] フィルタータイミングを新規追加しました。 `filtered` ステージのカラムが生成された後に実行されます。

- ベクターデータに対してLZ4/Zstd/zlibの圧縮をサポートしました。

- `_key` のようなアクセサへのエイリアスをサポートしました。

- [logical_range_filter] 大きい結果セットに対するウィンドウ関数の動作を最適化しました。一致するレコードが十分見つかった場合は、残りのウィンドウに対してウィンドウ関数を適用しません。

  TODO: この最適化は、最適化によるオーバーヘッドが無視出来ない場合、小さな結果セットに対しては、無効になります。 オーバーヘッドがどのくらいになるのかは、まだ評価出来ていません。

- [select] `match_escalation` パラメーターを追加しました。`--match_escalation yes` とすることによって、マッチ演算のエスカレーションを強制的に有効にします。このパラメータは、 `--match_escalation_threshold 99999....999` よりも強力です。`match_escalation yes` は、 `SOME_CONDITIONS && column @ 'query'` もエスカレーションしますが、 `--match_escalation_threshold` ではしないためです。

  デフォルトは、 `--match_escalation auto` です。これは、既存の動作と同じです。

  `--match_escalation no` とすることで、マッチ演算のエスカレーションを無効にできます。これは、 `--match_escalation_threshold -1` と同様の動きになります。

- [httpd] バンドルしているnginxのバージョンを1.13.10に更新しました。

### 修正

- 共通接頭辞がどのトークンにもマッチしない時にメモリリークする問題を修正しました。[GitHub#820] [村上さんがパッチ提供]

- 同一プロセスで複数のデータベースを開いている時に、異なるデータベースのキャッシュを使用してしまう問題を修正しました。

- 誤ったインデックスが構築される問題を修正しました。この問題は、インデックスカラムのソースがベクターカラムでかつ、 `WITH_SECTION` を指定していない時だけ発生します。

- 比較時(>,>=,<,<=,==,!=)に定数がオーバーフローまたは、アンダーフローし得る問題を修正しました。

### 感謝

- 村上さん

## 8.0.0リリース - 2018-02-09

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

### 改良

- [select] `--drilldown_adjuster` と `drilldowns[LABEL].adjuster` を追加しました。drilldown結果に対して、スコア調整できるようになります。

- [動的なインデックス構築方法] 環境変数の名前を `GRN_II_REDUCE_EXPIRE_ENABLE` から `GRN_II_REDUCE_EXPIRE_THRESHOLD` へ変更しました。

  `GRN_II_REDUCE_EXPIRE_THRESHOLD=0 == GRN_II_REDUCE_EXPIRE_ENABLE=no` 。 `GRN_II_REDUCE_EXPIRE_THRESHOLD=-1` とすると、しきい値は `ii->chunk->max_map_seg / 2` となります。`GRN_II_REDUCE_EXPIRE_THRESHOLD > 0` とすると、しきい値は `MIN(ii->chunk->max_map_seg / 2, GRN_II_REDUCE_EXPIRE_THRESHOLD)` となります。デフォルト値は、 `GRN_II_REDUCE_EXPIRE_THRESHOLD=32` です。

- [between] 境界値なしの `between()` を受け付けるようにしました。`between()` の引数の数が3つでも実行できます。2番目と3番目の引数が境界を含むものとして処理されます。

### 修正

- ハッシュテーブルのメモリリークを修正しました。 [GitHub:mroonga/mroonga#190][fuku1さんの報告]

- 配列のメモリリークを修正しました。

- [select] `output_columns` で結果の変化する関数を使っている時にキャッシュしないようにしました。

- [Windows] `WSASend` が適切なエラーコードを返すようにしました。

### 感謝

- fuku1さん

## 7.1.1リリース - 2018-01-29

### 改良

- [Ubuntu] Ubuntu 17.04（Zesty Zapus）のサポートをやめました。2018年1月13日でサポートが切れた（EOLになった）ためです。

- Quorum matchをサポートしました。スクリプト構文でもクエリー構文でもquorum matchを使うことができます。

  TODO: quorum matchの構文をドキュメントへ追加、それらのドキュメントへのリンク生成

- スクリプト構文で類似度のカスタマイズをサポートしました。スクリプト構文内で類似度のカスタマイズができます。

  TODO: 類似度のカスタマイズの構文をドキュメントへ追加、それらのドキュメントへのリンク生成

- [grndb][--force-lock-clear] `--force-lock-clear` を追加しました。このオプションは、データベースやテーブル、データカラムのロックを強制的に解除します。データベースやテーブル、データカラムにロックが残っていても再度データベースを使えるようになります。

  しかし、このオプションはとても危険です。通常は使うべきではありません。データベースが壊れている場合は、データベースは依然として破損しています。このオプションはロックを無視するだけです。

- [load] サロゲートペアをエスケープ可能にしました。例えば、 `\uD83C\uDF7A` は `🍺` として処理されます。

- [Windows] Windows上でスパースファイルを使用するように変更しました。ディスク容量を節約できます。パフォーマンス上のデメリットはありません。

- [動的なインデックス構築方法] インデックスカラム内のメモリーマップをいつ開放するかをコントロールする環境変数 `GRN_II_REDUCE_EXPIRE_THRESHOLD` を追加しました。デフォルトは `-1` です。 `-1` のときはインデックスカラムのサイズによって動的に開放するタイミングを決めます。インデックスカラムが小さければ頻繁に解放し、大きければ頻度を下げます。

  `0` を設定すると従来と同じ挙動になります。従来の挙動とは、Groongaは開放できそうなときはいつも開放しようとするという挙動です。

- [logical_range_filter] [post_filter]フィルタータイミングを新規追加しました。 `filtered` ステージで生成されるカラムが生成された後に実行されます。

### 修正

- 参照ベクタのインデックスを作成する際に使用するリソースを削減しました。[GitHub#806][村上さんが報告]

- [table_create] `token_filters` が無効であってもテーブルが作成される不具合を修正しました。

### 感謝

- 付超群さん

- 村上さん

## 7.1.0リリース - 2017-12-29

### 改良

- [load] `load` コマンドのクエリーログのフォーマットを改良しました。`load` コマンドのクエリーログに以下の項目が追加されます。

  > - ロードしたレコード数を表示します。

  > - ロードがエラーになったレコードとカラムの数を表示します。

  > - ロード後の総レコード数を表示します。

- [logical_count] `logical_count` コマンドのクエリーログのフォーマットを改良しました。`logical_count` コマンドのクエリーログに以下の項目が追加されます。

  > - マッチしたレコード数を表示します。

- [logical_select] `logical_select` コマンドのクエリーログのフォーマットを改良しました。 `logical_select` コマンドのクエリーログに以下の項目が追加されます。

  > - マッチしたレコード数を表示します。

  > - ドリルダウンした数を表示します。

  > - ラベルつきのドリルダウンをした数を表示します。

  > - それぞれのシャードで検索にマッチした数を表示します。

  > - 検索対象のシャードの情報を"[...]"を使って表示します。

- [delete] `delete` コマンドのクエリーログのフォーマットを改良しました。 `delete` コマンドのクエリーログに以下の項目が追加されます。

  > - 削除したレコード数と削除に失敗したレコード数を表示します。

  > - 削除後に残ったレコード数を表示します。

- [Groonga HTTPサーバー] `groonga -s` で実行したサーバーをC-c で確実に停止出来るようにしました。

- Lisp表現( `#<nan>` 、 `#i1/0` 、 `#-i1/0` )の代わりに `Nan` と `Infinity` 、 `-Infinity` を使用するように改良しました。

- ドリルダウンでベクター型のカラムをサポートしました。

- 部分的に正規表現を用いた検索から、キーワードを抽出出来るように改良しました。これにより、正規表現を用いた検索に `highlight_html` と `snippet_html` を使えるようになります。[takagi01さんに報告いただきました]

- `grn_bulk_*()` APIにおいて、 `realloc()` が呼ばれる回数を削減しました。

  Windowsにおいて出力が大きいケースでパフォーマンスが向上します。例えば、出力が100MBを超える場合には、約100倍速くなります。

  `realloc()` はWindowsでは重い処理であるためです。

- `GRN_II_OVERLAP_TOKEN_SKIP_ENABLE` の値にyesが設定された時のみ `GRN_II_OVERLAP_TOKEN_SKIP_ENABLE` を有効にするようにしました。

- `GRN_NGRAM_TOKENIZER_REMOVE_BLANK_DISABLE` は非推奨になりました。代わりに `GRN_NGRAM_TOKENIZER_REMOVE_BLANK_ENABL=no` を使って下さい。

- 関数 `index_column_source_records` を新規に追加しました。インデックスカラムのソースを取得することができます。[村上さんがパッチを提供]

- [select] offsetに負の値を設定出来るようにしました。

- 固定サイズのカラムの値を取得する際のパフォーマンスを向上しました。

- [groonga 実行ファイル] groongaコマンドの引数に `--listen-backlog` オプションを追加しました。listenシステムコールのbacklogをカスタマイズできます。

- [httpd] バンドルしているnginxのバージョンを1.13.8に更新しました。

### 修正

- `highlight_full` 関数を使用するとメモリリークする問題を修正しました。

- Mroongaで以下ような呼び出しを行った際にクラッシュする問題を修正しました。

  > 1. `grn_expr_append_const("_id")`

  > 2. `grn_expr_append_op(GRN_OP_GET_VALUE)`

### 感謝

- takagi01

- 村上さん

## 7.0.9リリース - 2017-11-29

### 改良

- Apache Arrowの新しいバージョンをサポートしました。このリリースでは、Apache Arrowサポートを有効にするには0.8.0以降が必要です。

- [sharding] 動的カラムの新しいAPIを追加しました。

  - Groonga::LabeledArguments

- [sharding] 便利メソッドである `Table#select_all` を追加しました。

- [logical_range_filter] 動的カラムをサポートしました。 `initial` と `filtered` ステージのみをサポートしています。

- [logical_range_filter] `cache` 引数と動的カラムに関するドキュメントを追加しました。

- [logical_count] 動的カラムをサポートしました。`initial` ステージのみサポートしています。

- [logical_count] 名前付き引数のドキュメントを追加しました。

- [select] `--match_columns _key` をインデックスを使わない場合でもサポートしました。

- [in_values] 126を超える引数を指定できるようにしました。 [GitHub#760] [GitHub#781] [groonga-dev,04449] [むらたさんが報告]

- [httpd] バンドルしているnginxのバージョンを1.13.7に更新しました。

### 修正

- [httpd] 古いバージョンのGroongaがすでにインストールされている場合にそちらを参照してしまい、ビルドエラーになる問題を修正しました。　[GitHub#775] [myamanishi3さんが報告]

- [in_values] `in_values` に多すぎる引数を指定するとクラッシュする不具合を修正しました。この不具合は126を超える引数をサポートする過程で見つかりました。 [GitHub#780]

- [cmake] LZ4 と MessagePack をビルド時に正しく検出できるようにしました。 [Sergei Golubchikさんが報告]

- [静的なインデックス構築方法] ベクターカラムの静的索引構築時に必要以上のリソースを使用する問題を修正しました。1つのベクターカラムの要素数が多く、大量のレコードがある場合はGroongaがクラッシュしていました。 [groonga-dev,04533][内山敏郎さんが報告]

### 感謝

- むらたさん

- myamanishi3さん

- Sergei Golubchikさん

- 内山敏郎さん

## 7.0.8リリース - 2017-10-29

### 改良

- [windows] クラッシュした際にバックトレースを出せるようにしました。関数呼び出しだけでなく、ソースコードの該当行も可能な限り表示します。バックトレースのサポートにより、問題の素早い解決につながります。

- `QUERY_NO_SYNTAX_ERROR` を指定してあれば "( )" を `--query` に指定して実行できるようにしました。 以前のバージョンでは、エラーになっていました。 [GitHub#767]

- `QUERY_NO_SYNTAX_ERROR` を指定してあれば "(+)" を `--query` に指定して実行できるようにしました。 以前のバージョンでは、エラーになっていました。 [GitHub#767]

- `QUERY_NO_SYNTAX_ERROR` を指定してあれば `--query "~y"` (~ではじまる)クエリーを実行できるようにしました。 以前のバージョンでは、エラーになっていました。 [GitHub#767]

- `expired` のログレベルを `info` から `debug` に変更しました。 `2017-10-29 14:05:34.123456|i| <0000000012345678:0> expired i=000000000B123456 max=10 (2/2)` このメッセージはインデックスをメモリーにマップした後で開放されたときに記録されます。つまり、メモリーの使用状況に関するデバッグには有用ですが、通常の運用においては有用ではありません。そのためログレベルを `debug` に変更しました。

- Ubuntu 17.10 Artful Aardvarkをサポート。

### 修正

- [dat] データベースを拡張する際、意図せず大きなファイルが(ワーストケースで)作成されてしまうことのある不具合を修正しました。この不具合はインデックスカラムを頻繁に作成/削除を繰り返したときに発生する可能性があります。7.0.7ではこの不具合に関連して"大量にキーを削除したケースで `table_create` に失敗する"問題を修正しましたが、その修正が不十分なケースに対応しました。

- [logical_select] `offset` と `limit` が複数のシャードに対して適用されたとき、実際よりも少ないレコードが返される不具合を修正しました。

## 7.0.7リリース - 2017-09-29

### 改良

- `QUERY_NO_SYNTAX_ERROR` を `+` のみのクエリーに指定したときにも動作するようにしました。以前のバージョンではそのようなクエリーはエラーになっていました。

- [httpd] バンドルしているnginxのバージョンを1.13.5に更新しました。

- [dump] 引数のデフォルト値を構文のセクションに追加しました。

- [コマンドバージョン] `--default-command-version 3` に対応しました。

- 関数呼び出し時に検索結果をキャッシュできるようにしました。ほとんどの関数の呼び出し結果はキャッシュされます。例外は `now()` と `rand()` を使った場合です。標準でキャッシュするように振る舞いを変更したので、新たにAPIを追加しました。

  - `grn_proc_set_is_stable()` を追加。

  - `grn_proc_is_stable()` を追加。

  呼び出しごとに結果が異なる関数を新規に追加する場合、`grn_proc_is_stable(ctx, proc, GRN_FALSE)` を呼ばなければなりません。もし呼ばなかった場合には、検索結果がキャッシュされるので、期待と異なり誤った結果を返します。

### 修正

- [windows] `database_unmap` が実行される前のファイルハンドルのエラー処理を適切に行うようにしました。`database_unmap` 実行前にリクエストがキャンセルされた場合、排他制御部分が未初期化となる場合がありました。その場合、クラッシュしていました。

- [トークナイザー] トークナイザー名のドキュメントを修正しました。`TokenBigramIgnoreBlankSplitSymbolAlpha` や `TokenBigramIgnoreBlankSplitSymbolAlphaDigit` であるべきでした。

- エラー時に空のファイルが残らないようにしました。

  以前のバージョンでは、空のファイルがエラー時に残っていました。

  再現するためのシナリオは以下です。:

  > 1. `grn_fileinfo_open` によりファイルの作成に成功する

  > 2. `DO_MAP` によりファイルマッピングに失敗する

  そのような場合、Groongaの管理下にないファイルのせいで「すでにファイルが存在します。」という別のエラーが発生します。そういったファイルは後始末の段階で削除すべきでした。

- 短時間に多数の更新を行っている状況で検索した場合にクラッシュすることがある不具合を修正しました。

- [table_create] 大量に削除されたキーがDATテーブルに存在する場合、`table_create` の実行に失敗する不具合を修正しました。

## 7.0.6リリース - 2017-08-29

### 改良

- 前方一致検索を複数インデックスを指定してできるようになりました。 (例 `--query "Foo*" --match_columns "TITLE_INDEX_COLUMN||BODY_INDEX_COLUMN"`)

- [window_count] `window_count` 関数を追加しました。検索した結果にカウントした値を追加するのに使います。検索結果をもとに分析したり、カウント結果をもとにフィルタしたりすると便利です。

- 以下のAPIを公開しました。

  - `grn_obj_get_disk_usage()` を追加。

  - `GRN_EXPR_QUERY_NO_SYNTAX_ERROR` を追加。

  - `grn_expr_syntax_expand_query_by_table()` を追加。

  - `grn_table_find_reference_object()` を追加。

- [object_inspect] 指定したオブジェクトのディスク使用量を表示できるようになりました。

- クエリーをパースする際にフォールバックする機能をサポートしました。 `QUERY_NO_SYNTAX_ERROR` フラグが `query_flags` に指定されていると有効になります。(標準では無効です) このフラグが設定されていると、シンタックスエラーが発生しなくなります。例えば、"A +" というクエリーは自動的にエスケープされて "A +" という扱いになります。この振る舞いはアプリケーションがユーザーの入力をそのまま検索語句として使い、シンタックスエラーやログに記録されないようにしたい場合に便利です。

- クエリー内の語のスコアを調整できるようになりました。">", "<" と "~"がサポートされています。例えば ">Groonga" は "Groonga" のスコアをインクリメントします。"<Groonga" は "Groonga" のスコアをデクリメントします。"~Groonga" は検索結果についてマッチしたドキュメントのスコアをデクリメントします。"~" は検索結果そのものには影響しません。

- テーブルを削除するときのパフォーマンスを改善しました。 `thread_limit=1` する必要はありません。参照されているテーブルが存在するかチェックする処理をオブジェクトを開かなくてもできるようにしました。その結果としてパフォーマンスが改善しました。

- [httpd] バンドルしているnginxのバージョンを1.13.4に更新しました。

### 修正

- [dump] 7番目の引数 ( `--sort_hash_table` )が名前無しだと無視される不具合を修正しました。

- [schema] コマンドラインパラメータの誤りを修正しました。source であるべきところが sources になっていました。[groonga-dev,04449] [むらたさんが報告]

- [ruby_eval] ruby_evalコマンドがシンタックスエラーのときにクラッシュする問題を修正しました。 [GitHub#751] [ryo-pinusさんがパッチ提供]

### 感謝

- murata satoshi

- ryo-pinus

## 7.0.5リリース - 2017-07-29

### 改良

- [httpd] バンドルしているnginxのバージョンを1.13.3に更新しました。セキュリティーに関する修正(CVE-2017-7529)を含んでいます。

- [load] UInt64の最大値をロードできるようにしました。以前のバージョンでは意図せず0に変換されてしまっていました。

- 以下のAPIを公開しました。

  - `grn_window_get_size()` [GitHub#725] [村上さんがパッチ提供]

- [math_abs] 絶対値を計算するための `math_abs()` 関数を追加しました。 [GitHub#721]

- `grn_default_logger_set_path()` と `grn_default_query_logger_set_path()` をスレッドセーフにしました。

- [Windows] バンドルしているpcreを8.41に更新しました。

- [normalize] エラー時に冗長な空文字列が出力されないようにしました。

- [functions/time] 0除算が発生したときにエラーメッセージを出力するようにしました。 [GitHub#733] [村上さんがパッチ提供]

- [windows] `ERROR_NO_SYSTEM_RESOURCES` エラーを `GRN_RESOURCE_TEMPORARILY_UNAVAILABLE` にマッピングするようにしました。以前は `rc=-1` をエラーコードとして返していました。ただし実際にどんな問題がおきたのかこれではわかりにくいので、 今回の修正では `rc=-12` を返すようにしています。

- [functions/min][functions/max] ベクターカラムをサポートしました。これでカラムがスカラーなのかベクターなのか気にせず使えるようになりました。 [GitHub#735] [村上さんがパッチ提供]

- [dump] `--sort_hash_table` オプションをサポートしました。ハッシュテーブルの `_key` でのソートには `--sort_hash_table yes` を指定します。

- [between] インデックスカラムを指定できるようになりました。 [GitHub#740] [村上さんがパッチ提供]

- [load] Apache Arrow 0.5.0 以降をサポート。

- [エラーメッセージの解析方法] エラーメッセージの解析方法のドキュメントを追加しました。

- [Debian GNU/Linux] ソースからビルドするときに必要なパッケージのリストを更新しました。

- [Ubuntu] Ubuntu 16.10（Yakkety Yak）のサポートをやめました。2017年7月20日でサポートが切れた（EOLになった）ためです。

### 修正

- テキスト型( `ShortText` など)のベクターカラムに対するインデックスを正しく構築できるようにしました。この修正でインデックス更新後に全文検索でマッチしない問題が解決します。 [GitHub#494]

- [thread_limit] `thread_limit?max=1` というリクエストが同時にきたときにデッドロックが発生する問題を修正しました。

- [groonga-httpd] デフォルトのPIDのパスと再起動時に想定しているPIDのパスがあっていない問題を修正しました。そのせいで groonga-httpd の再起動に失敗していました。 [GitHub#743] [sozakiさんが報告]

### 感謝

- 村上さん

## 7.0.4リリース - 2017-06-29

### 改良

- 物理的なファイルの作成/削除のログを障害の切り分けのために記録するようにしました。 [GitHub#700,#701]

- [in_records] 固定長カラムの検索パフォーマンスを改善しました。速度が50%程度改善する可能性があります。

- [grndb] `--log-path` オプションを追加しました。

- [grndb] `--log-level` オプションを追加しました。

- 以下のAPIを公開しました。

  - `grn_operator_to_exec_func()`

  - `grn_obj_is_corrupt()`

- "固定長カラム 演算子 定数" というようなクエリのパフォーマンスを改善しました。対応している演算子は `==`, `!=`, `<`, `>`, `<=` と `>=` です。

- "カラム 演算子 値 && カラム 演算子 値 && ..." というようなクエリのパフォーマンスを改善しました。

- [grndb] `grndb check` で壊れたオブジェクトの検出をサポートしました。

- [io_flush] `--only_opened` オプションをサポートしました。開いているデータベースオブジェクトのみをフラッシュすることができます。

- [grndb] 参照先のない "inspect" オブジェクトの検出と削除をサポートしました。この状態はコマンド名が `inspect` から `object_inspect` に変更されたことによって発生していました。

### 修正

- [rpm][centos] カスタマイズ版のビルドで意図しないマクロ展開が発生する問題を修正しました。この不具合はGroongaをSRPMからビルドする際にspecファイルの `additional_configure_options` パラメータを使ってリビルドするときのみ発生していました。

- `grn_table_setoperation()` のNULLチェックを追加しました。インデックスが壊れている際に、クラッシュする可能性がありました。 [GitHub#699]

### 感謝

## 7.0.3リリース - 2017-05-29

### 改良

- [select] インデックス名を指定した全文検索 のドキュメントを追加しました。

- [インデックス] どのレコードに対するポスティングリストが長すぎるのかわかるように、警告メッセージをログに出すようにしました。

- [load][dump] Apache Arrowをサポートするようにしました。 [GitHub#691]

- [cmake] 静的ライブラリとしてビルドする際に、LZ4をリンクできるようにしました。 [Sergei Golubchikさんがパッチを提供]

- [delete] キャンセルできるようにしました。

- [httpd] バンドルしているnginxのバージョンを1.13.0に更新しました。

- 以下のAPIを公開しました。

  - `grn_plugin_proc_get_caller()` を追加。

- インデックスカラムに関連した関数とセレクタを追加しました。

  - 追加されたセレクタ: `index_column_df_ratio_between()`

  - 追加された関数: `index_column_df_ratio()`

### 修正

- [delete] エラーが適切にクリアされていない不具合を修正しました。そのせいで、後続の削除処理に影響し意図しない振る舞いをしていました。

- [windows] ファイルを `O_CREAT` フラグ付きで開くときに、IOのバージョンが正しく検出されない不具合を修正しました。

- [vector_slice] (型のサイズが)4バイトでないベクターカラムをsliceできない不具合を修正しました。 [GitHub#695] [村上さんがパッチ提供]

- (型のサイズが)4バイトでないベクターカラムでベクターの要素をインデックスで指定するとシーケンシャルサーチでマッチしない不具合を修正しました。 [GitHub#696] [村上さんがパッチ提供]

- [logical_select] `min` に月の最終日を指定すると "argument out of range" が発生する不具合を修正しました。

### 感謝

- Sergei Golubchikさん

- 村上さん

## 7.0.2リリース - 2017-04-29

### 改良

- [logical_select] drilldowns[${LABEL}].columns[${NAME}].window.sort_keys と drilldowns[${LABEL}].columns[${NAME}].window.group_keys で複数のキーを指定できるようになりました。

- [Windows] バンドルしているLZ4を1.7.5に更新しました。

- [cache] 永続化キャッシュをサポートしました。

- [log_level] 英語のドキュメントを更新しました。

- 以下のAPIを公開しました。

  - `grn_set_default_cache_base_path()`

  - `grn_get_default_cache_base_path()`

  - `grn_persistent_cache_open()`

  - `grn_cache_default_open()`

- [`groonga --cache-base-path`] 永続キャッシュを使うための新しいオプションを追加しました。

- [groonga-httpd] [groonga_cache_base_path] 永続キャッシュを使うための新しい設定を追加しました。

- [Windows] バンドルしているmsgpackを2.1.1に更新しました。

- [object_inspect] カラム情報を表示するだけでなく、インデックスカラムの統計情報も表示できるようにしました。

- 正規表現の「 `.*` 」というパターンでインデックスを使って検索できるようになりました。 この機能はデフォルトで有効です。環境変数に `GRN_SCAN_INFO_REGEXP_DOT_ASTERISK_ENABLE=no` を設定すると無効化できます。

- [in_records] 既存のテーブルを条件のパターンを指定するのに使うことのできる関数を追加しました。

- [Ubuntu] EOLのため、Ubuntu 12.04のサポートをやめました。

### 修正

- [logical_select] 異なるキャッシュが使われてしまう不具合を修正しました。この問題は動的カラムを使っているときに発生していました。

- [logical_select] 動的カラムが作成されない不具合を修正しました。レコードにマッチしない場合に発生していました。

- [reindex] reindexコマンドの実行によりデータが失われてしまう不具合を修正しました。

- [httpd] 別のユーザーでワーカーを動かしている時、 quit と shutdown のレスポンスが壊れている問題を修正しました。 [GitHub ranguba/groonga-client#12]

## 7.0.1リリース - 2017-03-29

### 改良

- 以下のAPIを公開しました。

  - grn_ii_cursor_next_pos()

  - grn_table_apply_expr()

  - grn_obj_is_data_column()

  - grn_obj_is_expr()

  - grn_obj_is_scalar_column()

- [column_copy] 参照型のベクタのダンプをサポートしました。

- [load] `array<object>` スタイルの重み付きベクターカラムのloadをサポートしました。 `array<object>` の例: `[{"key1": weight1}, {"key2": weight2}]`

- インデックスを使った `!(XXX OPERATOR VALUE)` の検索をサポートしました。演算子として `>` だけでなく、 `>=`、 `<`、 `<=`、 `==` や `!=` も使えます。

- インデックスを使って `!(column == CONSTANT)` を検索できるようになりました。例えば `!(column == 29)` などです。

- `!` の最適化を以下のパターンでサポートしました。

  - `!(column @ "X") && (column @ "Y")`

  - `(column @ "Y") && !(column @ "X")`

  - `(column @ "Y") &! !(column @ "X")`

- `XXX || !(column @ "xxx")` をインデックスを使って検索できるようになりました。

- [dump] `'{"x": 1, "y": 2}'` というスタイルを参照されていない重み付きベクターカラムで使うようにしました。この変更は古いGroongaには影響しません。もともとサポートされているからです。

- [実験的] `GRN_ORDER_BY_ESTIMATED_SIZE_ENABLE` 環境変数をサポートしました。この変数はクエリの最適化を予想されるヒット件数に応じて行うかどうかを切り替えるのに使用します。この機能はデフォルトでは無効です。有効にするには `GRN_ORDER_BY_ESTIMATED_SIZE_ENABLE=yes` を指定します。

- [select] `columns` や `drilldown` の評価結果をクエリログに追加するようにしました。

- [select] `drilldown` のクエリログのフォーマットを変更しました。これは非互換な変更ですが、クエリログを変換するようなプログラムを独自に開発しているユーザー以外には影響ありません。

- [table_remove] 一時的なメモリ使用量を削減しました。スレッドの最大数が0のときに有効になります。

- [select] `columns[LABEL](N)` がクエリログのフォーマットとして使われます。以前は `columns(N)[LABEL]` でした。

- [クエリ拡張] ベクターカラムを使った推奨例に更新しました。[ぐるなびさんが報告]

- ロック中にリクエストがキャンセルされたことを検出できるようにしました。これは `request_cancel` がロック中に意図せず無視されないようにします。

- [logical_select] `initial` および `filtered` 動的カラムをサポートしました。使用例は `--columns[LABEL].stage initial` や `--columns[LABEL].stage filtered` です。

- [logical_select] `match_columns` や `query` 、 `drilldown_filter` オプションをサポートしました。

- [highlight_html] 類似文書検索をサポートしました。

- [logical_select] `initial` および `filtered` 動的カラムをサポートしました。使用例は `--columns[LABEL].stage initial` や `--columns[LABEL].stage filtered` です。

- [logical_select] 動的カラムでウィンドウ関数をサポートしました。

- [select] 動的カラムに関するドキュメントを追加しました。

- [ウィンドウ関数] ウィンドウ関数のセクションをドキュメントに追加しました。

- [CentOS] EOLのため、CentOS 5のサポートをやめました。

- [httpd] バンドルしているnginxのバージョンを1.11.12に更新しました。

- ANDでのマッチ最適化を環境変数で無効化できるようにしました。この機能は `GRN_TABLE_SELECT_AND_MIN_SKIP_ENABLE=no` を設定することで無効化できます。デフォルトでは有効になっています。

- [vector_new] 新規ベクターを作成するための関数を追加しました。

- [select] `drilldown_filter` のドキュメントを追加しました。

### 修正

- [lock_clear] テンポラリデータベースに対して実行するとクラッシュする不具合を修正しました。

- 自然言語に対する動的インデックス更新でインデックスサイズが肥大化する問題を修正しました。Groonga 6.1.4から発生していました。

- [select] "A && B.C @ X" というクエリでマッチすべきレコードを返さないことがある不具合を修正しました。

- `grn_io_flush()` と `grn_io_expire()` がコンフリクトする問題を修正しました。この修正がないと、 `io_flush` と `load` が同時に特定のタイミングで実行されるとクラッシュする不具合がありました。

- [logical_table_remove] 最大スレッド数が1のときにクラッシュする不具合を修正しました。

### 感謝

- 株式会社ぐるなびさん

## 7.0.0リリース - 2017-02-09

### 改良

- [in_values] 参照型ベクターカラムのシーケンシャルサーチに対応しました。 [GitHub#629] [村上さんがパッチ提供]

- [select] 誤った `drilldown[LABEL].sort_keys` が指定されたとき、無視するのではなく、エラーを報告するようにしました。

- [select] DBのメタデータを不必要に更新しないようにしました。 `select` コマンドを使っているだけなのにDBにロックがかかったままになってしまうのを防ぎます。

- [lock_clear] `lock_clear` でDBのメタデータに対するロックも削除できるようにしました。

- [CentOS] GroongaをAmazon LinuxでもインストールできるようにEPELをデフォルトで有効にするようにしました。

- [query] `default_mode` オプションで "@X" スタイルのエイリアスが使えるようになりました。

- [query] 動作モードのリストに関するドキュメントを更新しました。動作モードの既定値は `MATCH` ("@") で全文検索を実行します。

- [rpm][centos] CentOS 7で groonga-token-filter-stem パッケージを提供するようにしました。 ステミングに対応するための `TokenFilterStem` トークンフィルターを提供します。　[GitHub#633] [Tim Bellefleurさんが報告]

- [window_record_number] `record_number` が非推奨になりました。代わりに `window_record_number` を使ってください。 `record_number` は互換性のためだけに残っています。

- [window_sum] `window_sum` ウィンドウ関数を追加しました。PostgreSQLのsum()と同様のウィンドウ関数を提供します。

- `TABLE_DAT_KEY` テーブルをインメモリで使ったときに静的インデックス構築をできるようにしました。 [GitHub#623] [村上さんが報告]

- バンドルしている鬼雲を6.1.1へと更新しました。

- `columns[LABEL].window.group_keys` をサポートしました。ウィンドウ関数をグループごとに提供することができます。

- [load] 誤ったキーが指定されていたときにエラーを報告するようにしました。キーの型が異なっている場合でも気付けるようになります。

- [load] `--output_errors yes` オプションをサポートしました。"yes"を指定すると、どのレコードのloadに失敗したのかエラーを取得できるようになります。この機能を使う場合には、コマンドバージョン3を指定します。

- [load] キーのキャストに失敗したときのエラーメッセージをわかりやすくしました。以前は単に "cast failed" と表示していましたが、テーブルのキーの型とキャスト対象となるキーの型もメッセージに含まれるようになりました。

- [httpd] バンドルしているnginxのバージョンを1.11.9に更新しました。

### 修正

- 存在しないソートキーを `drilldowns[LABEL]` や `slices[LABEL]` に指定するとJSONパースエラーとなる不具合を修正しました。 [GitHub#627] [村上さんがパッチ提供]

- 存在しないグループのサブレコードにアクセスしようとするとクラッシュする不具合を修正しました。例えば、 `drilldowns[LABEL].sort_keys _sum` を `calc_types` の指定なしに使っていた場合に問題が発生していました。 [GitHub#625] [村上さんがパッチ提供]

- tokenizerでエラーが発生するとクラッシュする不具合を修正しました。tokenizer と token filterを登録していて、tokenizer にエラーがあると発生していました。

- [window_record_number] ウィンドウ関数の引数が正しく渡されていない不具合を修正しました。 [GitHub#634] [村上さんがパッチ提供]

### 感謝

- 村上さん

- aomi-nさん

## 古いリリース

- News - 6.x
  - 6.1.5リリース - 2017-01-23
  - 6.1.4リリース - 2017-01-18
  - 6.1.3リリース - 2017-01-06
  - 6.1.2リリース - 2016-12-31
  - 6.1.1リリース - 2016-11-29
  - 6.1.0リリース - 2016-10-29
  - 6.0.9リリース - 2016-09-29
  - 6.0.8リリース - 2016-08-29
  - 6.0.7リリース - 2016-07-29
  - 6.0.5リリース - 2016-06-29
  - 6.0.4リリース - 2016-06-06
  - 6.0.3リリース - 2016-05-29
  - 6.0.2リリース - 2016-04-29
  - 6.0.1リリース - 2016-03-29
  - 6.0.0リリース - 2016-02-29
- News - 5.x
  - 5.1.2リリース - 2016-01-29
  - 5.1.1リリース - 2015-12-29
  - 5.1.0リリース - 2015-11-29
  - 5.0.9リリース - 2015-10-29
  - 5.0.8リリース - 2015-09-29
  - 5.0.7リリース - 2015-08-31
  - 5.0.6リリース - 2015-07-29
  - 5.0.5リリース - 2015-06-29
  - 5.0.4リリース - 2015-05-29
  - 5.0.3リリース - 2015-04-29
  - 5.0.2リリース - 2015-03-31
  - 5.0.1リリース - 2015-03-29
  - 5.0.0リリース - 2015-02-09
- News - 4.x
  - 4.1.1リリース - 2015-01-29
  - 4.1.0リリース - 2015-01-09
  - 4.0.9リリース - 2014-12-29
  - 4.0.8リリース - 2014-11-29
  - 4.0.7リリース - 2014-10-29
  - 4.0.6リリース - 2014-09-29
  - 4.0.5リリース - 2014-08-29
  - 4.0.4リリース - 2014-07-29
  - 4.0.3リリース - 2014-06-29
  - 4.0.2リリース - 2014-05-29
  - 4.0.1リリース - 2014-03-29
  - 4.0.0リリース - 2014-02-09
- News - 3.x
  - 3.1.2リリース - 2014-01-29
  - 3.1.1リリース - 2013-12-29
  - 3.1.0リリース - 2013-11-29
  - 3.0.9リリース - 2013-10-29
  - 3.0.8リリース - 2013-09-29
  - 3.0.7リリース - 2013-08-29
  - 3.0.6リリース - 2013-07-29
  - 3.0.5リリース - 2013-06-29
  - 3.0.4リリース - 2013-05-29
  - 3.0.3リリース - 2013-04-29
  - 3.0.2リリース - 2013-03-29
  - 3.0.1リリース - 2013-02-28
  - 3.0.0リリース - 2013-02-09
- News - 2.x
  - 2.1.2リリース - 2013-01-29
  - 2.1.1リリース - 2012-12-29
  - 2.1.0リリース - 2012-12-29
  - 2.0.9リリース - 2012-11-29
  - 2.0.8リリース - 2012-10-29
  - 2.0.7リリース - 2012-09-29
  - 2.0.6リリース - 2012-08-29
  - 2.0.5リリース - 2012-07-29
  - 2.0.4リリース - 2012-06-29
  - 2.0.3リリース - 2012-05-29
  - 2.0.2リリース - 2012-04-29
  - 2.0.1リリース - 2012-03-29
  - 2.0.0リリース - 2012-02-29
- News - 1.3.x
  - 1.3.0リリース - 2012-01-29
- News - 1.2.x
  - 1.2.9リリース - 2011-12-29
  - 1.2.8リリース - 2011-11-29
  - 1.2.7リリース - 2011-10-29
  - 1.2.6リリース - 2011-09-29
  - 1.2.5リリース - 2011-08-29
  - 1.2.4リリース - 2011-07-29
  - 1.2.3リリース - 2011-06-29
  - 1.2.2リリース - 2011-05-29
  - 1.2.1リリース - 2011-04-29
  - 1.2.0リリース - 2011-03-29
- バージョン1.1.xのお知らせ
  - 1.1.0リリース - 2011-02-09
- バージョン1.0.xのお知らせ
  - 1.0.8リリース - 2011-02-02
  - 1.0.7リリース - 2011-01-29
  - 1.0.6リリース - 2010-12-31
  - 1.0.5リリース - 2010-12-29
  - 1.0.4リリース - 2010-11-29
  - 1.0.3リリース - 2010-10-29
  - 1.0.2リリース - 2010-09-09
  - 1.0.1リリース - 2010-09-06
  - 1.0.0リリース - 2010-08-29
- バージョン0.xのお知らせ
  - 0.7.7リリース - 2010-08-25
  - 0.7.6リリース - 2010-08-19
- News in Senna period
  - Senna -> groonga - 2009-01-14
  - 2006-04-05
  - 2006-03-03
  - 2006-01-16
  - 2006-01-12
  - 2005-12-22
  - 2005-10-27
  - 2005-09-17
  - 2005-09-08
  - 2005-08-16
  - 2005-07-05
  - 2005-06-23
  - 2005-04-12