7  AND 検索を実装する

boolean 検索のサブセットである AND 検索を実装してみます. AND 検索のように, 検索結果に何らかのフィルターをかけるためには, 類似度定義ファイルのパート 5 を使います.

まずプログラムの仕様ですが,検索要求はユーザからの文章とします. ですから msearch2 を改造することになります. 出力は,検索要求に現れる検索単語をすべて含む文書のみとします. 類似度計算式は WT_SMART を使うことにします. ですから WT_SMART にパート 5 を加えることになります.

7.1 パート 5 の使い方

パート 5 を知るために,wsh の仕組をすこし詳しく説明します. wsh は検索要求 *q の各単語について, それを含む文書リストを WAM から索きます. 例えば,*q に単語 w1, w2, w3 がパックされているとします. また,それぞれの単語から索ける文書リストが以下のようだと仮定します. なお,WAM の仕様により,文書リストは常に文書番号でソートされています.

        w1 --> d2 d5 d10
        w2 --> d2 d10 d12
        w3 --> d3 d4 d10
文書 d2 に含まれる単語は w1 と w2 です. また,文書 d3 に含まれる単語は w3 のみです. 文書 d10 には w1, w2, w3 の全ての単語が含まれています. wsh ではこのような集計をヒープを使うことにより効率良く行っています(*3). 実際には,各単語に関する重みを加えて検索結果 *r に各文書をパックします. パート 5 はこのパッキングの直前に挿入されます. よってパート 5 では, 各文書に含まれる検索単語の情報を見ることができます. ここで,もし何らかの条件チェックをして, 検索結果へのパッキングを行わないこともできます. 今は,AND 検索ですので,検索単語が全てあらわれているかをチェックします.WT_SMART のパート 5 に以下を追加してみてください.
        5:
                if (qlen != qvec_h_len) {
                        goto s5_break;
                }
qlen は *q の長さです.qvec_h という配列に, 今見ている文書に含まれる *q 中の単語がパックされています(「*q 中の単語」という点に注意).qvec_h_len は,qvec_h の長さです. AND 検索ですので,qlen と qvec_h_len が等しければ, AND 条件を満たすことになります. そうでなければ,s5_break というラベルに飛んでいます.s5_break というラベルに飛ぶと, 今見ている文書を検索結果 *r へパックしません.

以上で AND 検索用の定義ファイルができました.WT_SMART にパート 5 を追加しただけですので, AND 条件を満たす文書については,WT_SMART の類似度式にしたがって類似度が計算されます. この定義ファイルの名前を WT_SMART_AND として, libae を更新しておきましょう.

検索プログラム msearch2.c では, wsh の呼びだしで指定している類似度定義式を,WT_SMART_AND と変更するだけです.

7.2 もっと簡単に簡易 boolean 検索を実装する

本章では,類似度定義ファイルのパート 5 を学ぶために自分で AND 検索を実装してみました. 実は,libae には簡易 boolean 検索の機能が既に組み込まれています.syminfo 型を再度見てみましょう.

        struct syminfo {
                symbol_t id;
                int TF, TF_d;
                int DF, DF_d;
                double weight;
                int attr;
        }
今までは,attr というメンバには常に WSH_OR を設定していました. これは OR 検索を指定していたことになります. つまり,各単語は OR で検索せよということです.attr にはこの他にも WSH_AND と WSH_NOT が指定できます. その名のとおり,これらは AND と NOT を実現します. 例えば今,単語番号 {1,2,3,4,5} からなる syminfo 型リストから検索を 始めるとしましょう. ここで,単語 1 と 3 は検索結果に必ず出現してほしいとします. 単語 2 と 4 は出現してもしなくても良いとします. また,単語 5 は出現してほしくないとします. この場合, syminfo 型リストの attr は {WSH_AND, WSH_OR, WSH_AND, WSH_OR, WSH_NOT} のように各々設定します. wsh は検索結果を調べ,attr で指定された制約を満すもののみを返します. 重み計算は wsh で指定した式がそのまま適用されます.

この方法は boolean 検索の一面のみしか実現していません. 括弧を使って複雑な検索式を構築することはできませんし, 否定も擬似否定でしかありません. 以上の点に注意して使ってください.


*3: 「WAM のごく簡単なチュートリアル」 で作った Msearch では, 全ての文書リストを一度 cat して, 文書番号で sort し,uniq して集計していました. これに比べ,ヒープを使った集計は非常に高速です.


6: 関連文書検索,適合性フィードバックを実装する」に戻る
1: はじめに」に戻る