pythonのwhooshで全文検索してみる
全文検索、一度やってみたかったのよね。 whooshってのが手っ取り早そう。
という訳で、使ってみました。
import os
import whoosh.fields
import whoosh.index
import whoosh.qparser
# ディレクトリをインデックスとして使うらしい。
# インデックスがすでにあるかどうかをチェック。
if os.path.exists('/tmp/index')
# 既存のインデックスを開く
ix = whoosh.index.open_dir('/tmp/index')
else:
# インデックスの構造を定義
schema = whoosh.fields.Schema(
# IDはユニーク・・・ってわけでもないらしい。
# とりあえず、インデックス化はされないとのこと。
name=whoosh.fields.ID(stored=True),
# n-gramで保存されるデータ。
# 全文検索する時はとりあえずこれだけで良いんじゃないだろうか。
body=whoosh.fields.NGRAM(stored=True)
)
# インデックスを作成
# ディレクトリがないとエラーになるみたいなので、mkdirで作っとく。
os.mkdir('/tmp/index')
ix = whoosh.index.create_in('/tmp/index', schema)
# インデックスを更新するためのものを作成
writer = ix.writer()
# データを追加してみる
# unicode型限定なので注意。
writer.add_document(name=u'aa', body=u'hello whoosh')
writer.add_document(name=u'bb', body=u'whoosh test')
writer.add_document(name=u'cc', body=u'test string')
# 更新したら必ずコミットする
writer.commit()
# 取り敢えず検索
# クエリを作成
parser = whoosh.qparser.QueryParser('body', ix.schema)
query = parser.parse(u'whoosh')
# そしたら検索。
# aa u'hello whoosh'
# bb u'whoosh test'
# みたいに表示されるはず。
results = ix.searcher().search(query)
for r in results:
print r['name'], repr(r['body'])
# データを削除する
# writerを作りなおさないといけないので。注意。
query = parser.parse(u'test')
writer = ix.writer()
writer.delete_by_query(query)
writer.commit()
# もっかい検索してみる
# bbが削除されているので、aaのみが表示されるはず。
query = parser.parse(u'whoosh')
for r in ix.searcher().search(query):
print r['name'], repr(r['body'])
だいたいこんなもんだろうか。 データの更新は、一旦削除してから追加し直すみたいね。
全体的に、ちょっとめんどい感じ。 もうちょいシンプルでいいから、なんか良いの無いかな・・・。
とはいえ、速度はすごい速いです。 インデックスの作成に時間が掛かる代わりに、検索が高速。
これで手頃に扱えると嬉しいんだけどねー・・・。ラッパーでも作ろうかしら。
参考: