三日で書くgroonga関数
TRANSCRIPT
![Page 1: 三日で書くGroonga関数](https://reader036.vdocuments.pub/reader036/viewer/2022071709/55a3e9811a28ab45268b45a8/html5/thumbnails/1.jpg)
三日で作る Groonga 関数
hotpepsi@twitter
![Page 2: 三日で書くGroonga関数](https://reader036.vdocuments.pub/reader036/viewer/2022071709/55a3e9811a28ab45268b45a8/html5/thumbnails/2.jpg)
Agenda filter で呼べる関数を自作する ただし三日くらいで
![Page 3: 三日で書くGroonga関数](https://reader036.vdocuments.pub/reader036/viewer/2022071709/55a3e9811a28ab45268b45a8/html5/thumbnails/3.jpg)
背景 しょぼいサーバでスループットを上げ
たい 更新中も検索を止めたくない
検索されるものは全部 Groonga につっこむ
![Page 4: 三日で書くGroonga関数](https://reader036.vdocuments.pub/reader036/viewer/2022071709/55a3e9811a28ab45268b45a8/html5/thumbnails/4.jpg)
処理したい内容 親子関係を持つテーブルがある 親と子の個数の比は 1:n ある条件で子テーブルを検索し、合致
する親テーブルを取得したい
具体的には : 商品 (1) : 在庫・価格 (n)
![Page 5: 三日で書くGroonga関数](https://reader036.vdocuments.pub/reader036/viewer/2022071709/55a3e9811a28ab45268b45a8/html5/thumbnails/5.jpg)
SQL の場合 子テーブルに親テーブルを JOIN
検索結果を親のキーで DISTINCT
Groonga の場合、素直にはできない ※ ドリルダウンすれば 2 度引きで可能
![Page 6: 三日で書くGroonga関数](https://reader036.vdocuments.pub/reader036/viewer/2022071709/55a3e9811a28ab45268b45a8/html5/thumbnails/6.jpg)
Groonga の場合 子テーブルで検索する
重複するキーを filter で捨てる
filter で使える関数を自作する必要がある
![Page 7: 三日で書くGroonga関数](https://reader036.vdocuments.pub/reader036/viewer/2022071709/55a3e9811a28ab45268b45a8/html5/thumbnails/7.jpg)
自作する関数の仕様 引数として親のキー( _key )をとる 格納済かどうかを返す
Int32 distinct(ShortText parent_key)
![Page 8: 三日で書くGroonga関数](https://reader036.vdocuments.pub/reader036/viewer/2022071709/55a3e9811a28ab45268b45a8/html5/thumbnails/8.jpg)
雛形 test/unit/fix/fixtures/modules/string.c に
ある str_len を参考にする 自作の関数を登録する :grn_proc_create
grn_proc_create(ctx, "str_len", strlen("str_len"), GRN_PROC_FUNCTION, func_str_len, NULL, NULL, 0, NULL);
![Page 9: 三日で書くGroonga関数](https://reader036.vdocuments.pub/reader036/viewer/2022071709/55a3e9811a28ab45268b45a8/html5/thumbnails/9.jpg)
とりあえず版 登録 proc.c...grn_proc_create(ctx, "distinct", 8, GRN_PROC_FUNCTION, func_distinct, NULL, NULL, 0, NULL);...
![Page 10: 三日で書くGroonga関数](https://reader036.vdocuments.pub/reader036/viewer/2022071709/55a3e9811a28ab45268b45a8/html5/thumbnails/10.jpg)
とりあえず版 関数 proc.cstatic grn_obj *func_distinct(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) { int result = 0; grn_obj *obj; if (nargs == 1) { grn_obj *item_key = args[0]; result = _distinct(GRN_TEXT_VALUE(item_key), GRN_TEXT_LEN(item_key)); if ((obj = GRN_PROC_ALLOC(GRN_DB_UINT32, 0))) { GRN_UINT32_SET(ctx, obj, result); } } return obj;}
![Page 11: 三日で書くGroonga関数](https://reader036.vdocuments.pub/reader036/viewer/2022071709/55a3e9811a28ab45268b45a8/html5/thumbnails/11.jpg)
とりあえず版 中身 distinct.cc#include <string>#include <set>
typedef std::set<std::string> Map;static Map _map; // 格納済キーの保存庫
extern "C" int _distinct(const char *name, size_t length) { std::string _key(name, length); // std::string に変換 Map::iterator it = _map.find(_key); // キーを探す if (it != _map.end()) return 0; // 格納済なら 0 を返す _map.insert(key); // 格納する return 1;}
![Page 12: 三日で書くGroonga関数](https://reader036.vdocuments.pub/reader036/viewer/2022071709/55a3e9811a28ab45268b45a8/html5/thumbnails/12.jpg)
適当にビルドしてみる lib/ に distinct.cc を追加して make
よくわからないエラー ../lib/.libs/libgroonga.so: undefined
reference to `__cxa_begin_catch‘
g++ 経由でリンクしないと駄目
![Page 13: 三日で書くGroonga関数](https://reader036.vdocuments.pub/reader036/viewer/2022071709/55a3e9811a28ab45268b45a8/html5/thumbnails/13.jpg)
正式なやり方 configure.ac に AC_PROG_CXX を追加 lib/Makefile.am の
libgroonga_la_SOURCES に distinct.ccを追加
autoreconf で configure を再生成
![Page 14: 三日で書くGroonga関数](https://reader036.vdocuments.pub/reader036/viewer/2022071709/55a3e9811a28ab45268b45a8/html5/thumbnails/14.jpg)
autoreconf への道 色々更新が必要
autoconf-2.67 automake-1.11.1 libtool-2.2.6b
激しく遠い道のりなので以下略
![Page 15: 三日で書くGroonga関数](https://reader036.vdocuments.pub/reader036/viewer/2022071709/55a3e9811a28ab45268b45a8/html5/thumbnails/15.jpg)
手抜き Makefile.in に追記
.SUFFIXES に .cc を追加 CCLD を gcc から g++ に変更 ビルドルールに .cc.o を追加
![Page 16: 三日で書くGroonga関数](https://reader036.vdocuments.pub/reader036/viewer/2022071709/55a3e9811a28ab45268b45a8/html5/thumbnails/16.jpg)
デモ 商品テーブル item
ShortText 型 description 3 件
在庫テーブル stock item 型 i Time 型 date Int32 型 price 9 件
![Page 17: 三日で書くGroonga関数](https://reader036.vdocuments.pub/reader036/viewer/2022071709/55a3e9811a28ab45268b45a8/html5/thumbnails/17.jpg)
distinct なし select --table stock --output_columns
i._key,price
→ i._key が重複する
![Page 18: 三日で書くGroonga関数](https://reader036.vdocuments.pub/reader036/viewer/2022071709/55a3e9811a28ab45268b45a8/html5/thumbnails/18.jpg)
distinct あり select --table stock --filter
"distinct(i._key)" --output_columns i._key,price
→ i._key が重複しない
![Page 19: 三日で書くGroonga関数](https://reader036.vdocuments.pub/reader036/viewer/2022071709/55a3e9811a28ab45268b45a8/html5/thumbnails/19.jpg)
end of file