とりあえず、SQLite で FTS2 を使うことはできるようになった。次は Python から FTS2 を使えるようにしたいということでやってみる。
#179 Implement virtual table support や
#180 Implement loadable extensions を見ると pysqlite では、まだ FTS2 が使えないようだ。
enable_load_extension-r296.patch があるのだな。
しかし、考えてみたらモジュールを組み込んでコンパイルしてしまったので、もしかして行けるかな?と試してみる。VIRTUAL TABLE で引っかかるかなと思ったら使えてしまった。もう、VIRTUAL TABLE には対応できているのか。というか、SQLite に渡して実行してもらっているから、この手の使い方の場合は、通常のテーブルと同じで問題にならないようだ。
import MeCab
import pysqlite2.dbapi2 as sqlite
# とりあえず、日本語をまず分かち書きにしておく
# 挿入したいデータ
data = [
('日本語を使う', '日本語使ってやってみるよ。'),
('分かち書きはMeCab', '日本語の分かち書きはMeCabを使ってみる。'),
('メモメモ', '元のデータは分かち書きしてなくても大丈夫。'),
('こんな具合', 'こんな具合で日本語書いてる。') ]
# 分かち書きしておく
t = MeCab.Tagger ("-Owakati")
data = [(t.parse(x[0]), t.parse(x[1])) for x in data]
# 全文検索用のテーブルを作る
con = sqlite.Connection(":memory:")
con.execute("CREATE VIRTUAL TABLE memo using FTS2(title, body);")
cur = con.cursor()
# テーブルにデータを挿入する
sql_str = "insert into memo (title, body) values (?,?);"
cur.executemany(sql_str, data)
# 試してみる
print "テスト 1"
sql_str = "select rowid, title, body from memo where title match '日本語';"
res = list(con.execute(sql_str))
for l in res:
title = l[1].split()
body = l[2].split()
print l[0], "".join(title), "".join(body)
print "-" * 20
print "テスト 2"
sql_str = "select rowid, title, body from memo where body match '日本語';"
res = list(con.execute(sql_str))
for l in res:
title = l[1].split()
body = l[2].split()
print l[0], "".join(title), "".join(body)
print "-" * 20
そうすると、次のような出力が得られる。
テスト 1
1 日本語を使う 日本語使ってやってみるよ。
--------------------
テスト 2
1 日本語を使う 日本語使ってやってみるよ。
--------------------
2 分かち書きはMeCab 日本語の分かち書きはMeCabを使ってみる。
--------------------
4 こんな具合 こんな具合で日本語書いてる。
--------------------
ということで、とりあえず使えるようになった。が、こうやって、分かち書きをした文字列をテーブルに登録するやり方だと原文を取り出せないので、オリジナルと分かち書きをした FTS2 用のそれぞれの文字列をテーブルに保存しておかなければならなくなる。
これはちょっと記憶領域の点でも手間の点でも好ましくない。けど、これは誰かがそのうちやるだろうから、とりあえずここまでにしておく( 日本語用の tokenizer を作る人が出てくるだろうから )。
とりあえず、インチキで分かち書きをしたものを登録して、取り出してからスペースを削除している。このやり方だと、本当のスペースが消えてしまうのでダメだけど。とりあえず、ということで。