丸パクリで大成功!
成果物
情報源
こちらを丸パクリ。超感謝! ネ申!
事前準備
- SQLite3のソースコード入手&展開:
/tmp/work/sqlite-autoconf-3290000/
sudo apt install mecab mecab-utils libmecab-dev
/usr/include/mecab.h
/usr/lib/mecab
つまり以下を済ませておくこと。
FTS5_MeCabのソースコード入手
git clone https://github.com/thino-rma/fts5_mecab
コンパイル
gcc -g -fPIC -shared fts5_mecab.c -o fts5_mecab.so -I/usr/include -L/usr/lib -L/usr/lib/mecab -lmecab -I/tmp/work/sqlite-autoconf-3290000
fts5_mecab.so
ファイルが作成されたら成功。
SQLiteでライブラリをロードする
ターミナルで以下コマンドを実行する。
sqlite3
SQLite3対話モードになる。
sqlite>
ロードコマンドを実行。
.load ./fts5_mecab
以下が出力された。ログ?
sqlite3_ftsmecab_init()
準備完了。
全文検索する
FTSテーブルとデータを作成する。
CREATE VIRTUAL TABLE t1 USING fts5(x, tokenize = 'mecab'); insert into t1 values('ytyaruがMeCabで形態素解析をする。'); insert into t1 values('これはytyaruがMeCabを使った偉業である。');
create virtual table posts using fts5(title, content, tokenize = 'mecab');
全文検索してみる。
select * from t1('使った');
これはytyaruがMeCabを使った偉業である。
キタ━━━━(゚∀゚)━━━━!!
関連性の高い順でソートする
テーブルを作る。
create virtual table posts using fts5(title, content, tokenize = 'mecab'); insert into posts values('タイトル1', '本文1'); insert into posts values('タイトル2', '本文2'); insert into posts values('たいとる3', 'ほんぶん3'); insert into posts values('間違ったタイトルの書き方', '間違った本文の書き方'); insert into posts values('終わったタイトル', '終わった本文'); insert into posts values('English title 1', 'English content 1.'); insert into posts values('English title 2', 'English content 2.'); insert into posts values('english title 3', 'english content 3.');
全文検索する。
select * from posts where posts match 'タイトル' order by rank;
title content ---------- ---------- タイトル1 本文1 タイトル2 本文2 終わったタイトル 終わった本文 間違ったタイトルの書 間違った本文の書き方
ふつうに作った順。関連性の高さって何? キーワードの重複回数とか?
出力を加工する
SELECT highlight(posts, 0, '<b>', '</b>') FROM posts('タイトル');
highlight(posts, 0, '<b>', '</b>') ---------------------------------- <b>タイトル</b>1 <b>タイトル</b>2 間違った<b>タイトル</b>の書き方 終わった<b>タイトル</b>
環境構築
fts5_mecab.so
を所定のパスに保存する.sqliterc
を作る
1. fts5_mecab.so
を所定のパスに保存する
どこか整理されたパスにfts5_mecab.so
を保存する。
2. .sqliterc
を作る
~/.sqliterc
.load /home/pi/root/sys/env/tool/sqlite_ext/fts5_mecab.so .mode column .width 0 .headers on .timer on .nullvalue NULL
でも、SQLite3を使う自作スクリプトで余計な出力が出てしまうようになってバグった。全文検索を使うたびにload
するほうが良さそう。
オプション
特に必要なさそう。
vv
$ cd $HOME/usr/src/fts5_mecab $ gcc -g -fPIC -shared fts5_mecab.c -o fts5_mecab.so -I$HOME/usr/include -L$HOME/usr/lib -lmecab -DDEBUG $ LD_LIBRARY_PATH=$HOME/usr/lib $HOME/usr/bin/sqlite3 sqlite> .load /PATH/TO/fts5_mecab sqlite> CREATE VIRTUAL TABLE t1 USING fts5(x, tokenize = 'mecab vv');
#ifdef DEBUG if (p->verbose > 1) { // DEBUG LEVEL 2 // printf("pText (nText) = %s (%d)\n", pText, nText); printf("node info\n"); printf(" feature = %s\n", node->feature); printf(" surface = %s\n", node->surface); printf(" length = %d\n", node->length); printf(" rlength = %d\n", node->rlength); printf(" posid = %d\n", node->posid); printf(" char_type = %d\n", node->char_type); printf(" stat = %d\n", node->stat); printf("--------------\n"); } #endif
#ifdef DEBUG if (p->verbose > 1) { // DEBUG LEVEL 2 printf("calling xToken()\n"); printf(" tflags = 0\n"); printf(" pToken = %s\n", buf); printf(" nToken = %d\n", nlen); printf(" iStart = %d\n", offset); printf(" iEnd = %d\n", offset + nlen); printf("==============\n"); } #endif
品詞とかを取得できるのかな? 単なる文字列として出力するのでなくテーブルで欲しい。SQL関数にすれば面白いかも? このへんが参考になる?
stop789
$ cd $HOME/usr/src/fts5_mecab $ gcc -g -fPIC -shared fts5_mecab.c -o fts5_mecab.so -I$HOME/usr/include -L$HOME/usr/lib -lmecab -DSTOP789 $ LD_LIBRARY_PATH=$HOME/usr/lib $HOME/usr/bin/sqlite3 sqlite> .load /PATH/TO/fts5_mecab sqlite> CREATE VIRTUAL TABLE t1 USING fts5(x, tokenize = 'mecab stop789');
stop789
オプションを付与すると、posid
が7
,8
,9
のトークンが破棄されるらしい。posid
とは品詞IDのことみたい。
名詞 1 動詞 2 形容詞 3 副詞 4 助詞 5 接続詞 6 助動詞 7 連体詞 8 感動詞 9 * 10
つまり助動詞、連体詞、感動詞が削除される? と思ったが、品詞IDは自分で定義するみたい。それじゃ7,8,9固定値の意味は不定ということでは? 何か意味があるのだろうか。
コードは以下の部分と思われる。
#ifdef STOP789 if (!p->stop789 || node->posid > 9 || node->posid < 7) { rc = xToken(pCtx, 0, buf, nlen, offset, offset + nlen); #ifdef DEBUG _token_count += 1; } else { if (p->verbose > 0) { // DEBUG LEVEL 1 printf("increment _node_count [3]: %s\n", node->feature); } #endif } #else rc = xToken(pCtx, 0, buf, nlen, offset, offset + nlen); #ifdef DEBUG _token_count += 1; #endif #endif
所感
パクリ元が神すぎて感謝しかない。
対象環境
- Raspbierry pi 3 Model B+
- Raspbian stretch 9.0 2018-11-13
- bash 4.4.12(1)-release
- SQLite 3.29.0
$ uname -a Linux raspberrypi 4.19.42-v7+ #1218 SMP Tue May 14 00:48:17 BST 2019 armv7l GNU/Linux
前回まで
- SQLite3学習をはじめよう
- SQLite3学習 SQLiteについて
- SQLite3学習 SQLiteの適切な用途
- SQLite3学習 SQLiteの特徴
- SQLite3学習 SQLiteのクセ
- SQLite3学習 データ型とアフィニティ
- SQLite3学習 演算子の一覧
- SQLite3学習 よくある質問
- SQLite3学習 SQLiteダウンロード&コンパイル
- SQLite3学習 Tclで操作する
- SQLite3学習 ビルドオプション動作確認(SQLITE_ALLOW_URI_AUTHORITY)
- SQLite3学習 面白そうなコンパイルオプション
- SQLite3学習 SQLiteの拡張について
- SQLite3学習 JSON拡張
- SQLite3学習 JSON拡張(json_extract)
- SQLite3学習 JSON拡張(json_each)
- SQLite3学習 JSON拡張(json_tree オブジェクト→行)
- SQLite3学習 JSON拡張(json_tree オブジェクトツリー→行)
- SQLite3学習 JSON拡張(json_tree オブジェクト配列→行)
- SQLite3学習 JSON拡張(json_group_array 行→配列)
- SQLite3学習 JSON拡張(json_group_object 行→オブジェクト)
- SQLite3学習 JSON拡張(json_array_length)
- SQLite3学習 JSON拡張(json_type)
- SQLite3学習 JSON拡張(json_valid)
- SQLite3学習 JSON拡張(json_quote)
- SQLite3学習 JSON拡張(json_array)
- SQLite3学習 JSON拡張(json_object)
- SQLite3学習 JSON拡張(json_patch)
- SQLite3学習 JSON拡張(json_insert)
- SQLite3学習 JSON拡張(json_replace)
- SQLite3学習 JSON拡張(json_set)
- SQLite3学習 JSON拡張(json_remove)
- SQLite3学習 全文検索(FTS5)
- SQLite3学習 全文検索FTSを日本語で使う方法を調べてみた
- 形態素解析MeCabをインストールする