遅い→起動時

http://d.hatena.ne.jp/pmint/

新しいWikiEngineの検索機能

Wikiのシステム作りの途中経過。

codeなにがしに投稿していたサンプルの続編。

プロトタイプ03
X03.2011-12-08.zip
VS2008Proj、C#

稼働中
http://x03.pmint.name/

発想

WikiEngineは記法別の処理を行なうために、テキストを記法別オブジェクトに変換しているけど、もっと突き詰めればシンプルに曖昧検索を実装できそう。


→ 記法別にEqualメソッドのような評価方法を用意。「5cm」や「10kg」、「2011/11/11」などを記法にすれば近似値も見つけられる曖昧検索になりそう。


どんな記法を有効にするかはWiki(サイト)次第、つまり管理者次第。コードを書かずに検索処理をカスタマイズできる。


やりたいこと

形式がないようで少しはある(あってもよく崩れる)Wikiに似合うように
適当に、大体あってれば機能する検索処理を考えてみた。


例えば…

  • 2011/11/11を検索すると「2011/11/10」と書かれたページにもそこそこのスコアで適合するような
  • 2011/11/11を検索すると「2011/11/04」と書かれたページも(同じ曜日なので)そこそこのスコアで適合するような
  • 100円を検索すると「105円」と書かれたページと(税込みにした価格なので)最高のスコアで適合するような
  • 100円を検索すると「96円」と書かれたページと(税抜きにした価格なので)最高のスコアで適合するような


これらがプラグインで追加・無効化、設定で調整できるような。


やってみた

1つできれば他もできるので、とりあえずやりたいことを一部だけ実装。


このプロトタイプでできること

  • 数日ずれていても見つかる日付検索
  • 数文字違っていても見つかるテキスト検索

実装の内部

Wikiの記法→対応する記法オブジェクトに変換(記法以外のテキストはPlaintextというオブジェクトになる)


このプロトタイプは検索ワードと検索対象(Wikiページ)の類似度を見る。検索ワードと同じ表現が検索対象にもあれば適合したとみなす。ここまでは普通。


それをオブジェクト化した検索ワードと、オブジェクト化した検索対象(Wikiページ)間で行なう。


何を適合とみなすかは記法オブジェクト次第。
例えば日付は日付記法オブジェクトの中でシリアル値に変換、検索時にはシリアル値の差を使う。


その他実装の要点
  • 検索ワードも検索対象(Wikiページ)もオブジェクトに変換、他の処理はそこから行なう。同じ処理でオブジェクト化。
  • 比較する2オブジェクトは同じ型でなければならないので、同じ記法同士しか比較しない。
  • 日付はシリアル値に変換。検索ワード側とWikiページ側を比較して、差の小ささを評価。
  • プレーンテキストはbi-gramの一致率を評価。
  • 検索ワードがオブジェクト化によって細切れになってしまうので、複数適合した場合にその位置の近さも評価する。ページ上で高評価なオブジェクトが近くにあるとき評価をさらに高めればいい。ページ上でのオブジェクト間の距離を逆数にして評価に掛け合わせる。
  • 評価は記法別。なので、スコアを合算してはいけない。記法別スコアを合計しても1ページ全体のスコアとしては使えない。検索結果も記法別になる。検索ワード内にある記法別にスコアを求めて、そのいずれかでソート。
    …はToDoにして、このプロトタイプではページ上で最も高い評価を得た記法でソート。

どうなったか

プロトタイプ03
http://x03.pmint.name/


「ページを作り込むこと」でサイトとしてのWikiを改造できるように、検索機能を記法化したいので、プロトタイプでは検索をPukiWikiプラグイン記法っぽい書き方にしてみた。

&find(検索ワード, 検索対象になるページを示す何か);


この記法で検索ワードを書くと検索結果化するという寸法。「検索の保存」のようなこともできるし、検索ワード部分を動的にできれば検索結果を動的にすることもできる。




検索ワードを入れずに書くと検索欄になる。




好きなページの任意の位置に検索欄を埋め込める。送信ボタンでページリロード。検索ワード付き検索記法と同じ処理へ。





検索が記法になっているので、後から別の検索方法を実装・追加しやすいし、検索方法別に記法を用意するので、管理者によるサイトの設定ではなく、ページを書く人が見せたいように検索結果を選べる。


プロトタイプではやらなかったけど・・・
  • 日付の評価を多重化してもいい。日数の他に年数、月数、週数でも同じように計算、スコアに加える。
  • 検索方法を多重化してもいい。記法もプレーンテキストとする普通の全文検索でのスコアも表示してそれでソートできたり、上記方法のページスコアに加えちゃったり。
  • 検索記法はネスト可能にしたい。探索範囲として検索記法(検索ワード付き)を与えるとそれがサブクエリーになるように。一度の検索が複数回の絞り込み検索になる。管理者がWikiを作り込むのに使えるのでは。
  • 検索結果の見た目は検索記法のパラメーターで選択する以外に、検索記法を別の記法(テーブル記法)に入れるのもいいかも。記法をネストしたときはWiki記法でもHTMLでもなく、再処理しやすい形式で記法オブジェクト間でやり取りする仕組みにするつもり。汎用性のためString型のリストやハッシュで。