Whoosh+jieba中国語検索

5682 ワード

背景
最近、プロジェクトはWhooshのPythonが作成したインデックス検索モジュールを使います.中国語の資料が少なく、先輩のコードを見ても分からないことが多いことに気づきました.だから、自分で公式サイトのドキュメントに従って、自分の理解と公式サイトのよくない説明を書きました.
クイックハンド
いくつかのコアオブジェクトIndexSchema対象
Whooshを使用する前に、まずindexオブジェクトを作成する必要があります.indexオブジェクトはグローバルインデックスです.indexオブジェクトを作成する前に、indexオブジェクトのいくつかのプロパティを宣言する必要があります.そのため、これらのプロパティをパッケージするschemaオブジェクトを作成する必要があります.schemaには多くのFieldsがあります(1つのFieldはindexオブジェクトの情報ブロックです.つまり、私たちが検索する必要があるコンテンツです).
栗を挙げると、次のコードは「title」と「path」と「content」の3つのFieldsを含むschemaオブジェクトを作成します.
from whoosh.fields import Schema, TEXT, ID
schema = Schema(title=TEXT, path=ID, content=TEXT)

schemaオブジェクトを作成するには、Field nameとField typeをキーワードでマッピングする必要があります.上記のようにtitle=TEXTschemaオブジェクトが作成されると、次にcreate_inメソッドを使用してschemaのインデックスを作成します.
import os.path
from whoosh.index import create_in

if not os.path.exists("index"):
    os.mkdir("index")
idx = create_in("index", schema)

次に、作成したインデックスを次の2つの方法で開くことができます.
#       FileStorage  
from whoosh.filedb.filestore import FileStorage
storage = FileStorage(idx_path)  #idx_path      
idx = storage.open_index(indexname=indexname, schema=schema)

#       open_dir  
from whoosh.index import open_dir
idx = open_dir(indexname=indexname)  #indexname     
IndexWriter対象
indexオブジェクトがあると、検索する必要がある情報をindexに書き込む必要があるのでIndexWriterオブジェクトはadd_document(**kwargs)前に宣言した各種Fieldsにデータを書き込む方法を提供する
writer = idx.writer()  #IndexWriter  
writer.add_document(
    title=u"Document Title",
    path=u"/a",
    content=u"Hello Whoosh"
)  # Field   schema       
writer.commit()  #     document

次の点に注意してください.
  • フィールドごとに付与されるわけではない
  • Field伝値は必ずunicodeタイプの値
  • インデックスとして保存するフィールドがある場合は、別のオブジェクトをインデックスとして保存しながらunicode値を使用できます.
    writer.add_document(title=u"Title to be indexed", _stored_title=u"Stored title")    
    

    非同期処理が必要な場合は、非同期IndexWriterオブジェクトを作成できます.
    from whoosh.writing import AsyncWriter
    writer = AsyncWriter(index=index)
    

    BufferedWriterオブジェクトを作成するには、Bufferが必要です.
    from whoosh.writing import BufferedWriter
    # period   commit       ,limit          
    writer = BufferedWriter(index=index, period=120, limit=20)
    
    Searcher対象
    インデックスの検索を開始する前に、searcherオブジェクトを作成する必要があります.
    searcher = idx.sercher()
    

    しかし、一般的にはこのように検索器searcherを作成することはできません.これはインデックス検索が完了した後、検索器を閉じてメモリを解放することはできません(searcherがメモリを食べていることを知っていればいいです).私たちは一般的にwithsearcherオブジェクトを作成します.検索器の使用が完了した後、正しく閉じることを保証していません.
    with idx.sercher() as searcher:
        ...
    

    以上の書き方は
    try:
        searcher = idx.searcher()
        ...
    finally:
        searcher.close()
    

    検索器のsearch()メソッドはQuiryオブジェクトを入力する必要があります.Quiryオブジェクトを直接構築したり、query parserを使用してクエリーフィールドを解析したりすることができます.
    くりを一つあげる
    #         
    from whoosh.query import *
    myquery = And([Term("content", u"apple"), Term("content", "bear")]) 
    

    デフォルトのQueryParserではクエリー原語の使用が許可されていますANDORNOTSQLのように簡単!
    #            
    from whoosh.qparser import QueryParser
    parser = QueryParser("content", idx.schema)
    myquery = parser.parse(querystring)
    

    クエリー・オブジェクトを構築したら、検索器のsearch()メソッドを使用して検索できます
    results = searcher.search(myquery)
    print(results[0])
    {"title": "Document", "content": "Hello Whoosh"}
    

    より一般的にはページングクエリsearch_page()を使用します.
    results = searcher.search_page(myquery, page_num, page_len)
    

    注目すべきはsearch()デフォルトパラメータを受信weighting=BM25Fこれは検索の重みアルゴリズムでありwhoosh.scoring.Weightingオブジェクトであり、内蔵scoreメソッドを使用して検索の優先度を計算することでドキュメントインデックスをクエリーする
    jieba分詞と組み合わせて使用
    Whooshの基本的な使い方は以上の通りです.次にQueryStringに結巴分詞分析モジュールを追加します.
    jieba 0.30以降のバージョンではWhoosh用の分詞インタフェース:ChineseAnalyzerが追加されているので便利です
    まずWhoosh schemaオブジェクトの作成whoosh.fields.TEXT、デフォルトの宣言TEXT時フィールドのFieldAttributesデフォルトに属性analyzerがあります
    analyzerは__call__マジックメソッドを持つクラスで、TEXTワードドメインの解析を行い、呼び出し時にTEXTドメインの値を__call__処理する
    analyzerが受信したパラメータはunicode文字列で、戻り値は文字列カットで、栗を挙げる
    e.g.(
    ​ param = "Mary had a little lamb"
    ​ return = ["Mary", "had", "a", "little", "lamb"]
    )
    Whooshを使用しているStandardAnalyzer、英語の分詞器です.jiebaに接続するために、中国語の分詞を作るには、TEXT(analyzer=analysis.StandardAnalyzer())jiebaのChineseAnalyzerに置き換える必要があります
    from __future__ import unicode_literals
    from jieba.analyse import ChineseAnalyzer
    
    analyzer = ChineseAnalyzer()
    
    schema = Schema(title=TEXT(stored=True), path=ID(stored=True), content=TEXT(stored=True, analyzer=analyzer))
    
    idx = create_in("test", schema)
    writer = idx.writer()
    writer.add_document(
        title="test-document",
        path="/c",
        content="This is the document for test"
    )
    writer.commit()
    searcher = idx.searcher()
    parser = QueryParser("content", schema=idx.schema)
    
    for keyword in ("  "," ","first","  ","   ","  "):
        print("result of ",keyword)
        q = parser.parse(keyword)
        results = searcher.search(q)
        for hit in results:
            print(hit.highlights("content"))
        print("="*10)
    

    やはり便利です.