Blanktar

  1. top
  2. blog
  3. 2013
  4. 04

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'])

だいたいこんなもんだろうか。 データの更新は、一旦削除してから追加し直すみたいね。

全体的に、ちょっとめんどい感じ。 もうちょいシンプルでいいから、なんか良いの無いかな・・・。

とはいえ、速度はすごい速いです。 インデックスの作成に時間が掛かる代わりに、検索が高速。

これで手頃に扱えると嬉しいんだけどねー・・・。ラッパーでも作ろうかしら。


参考: