WordPress Related Post for Japanese で全文検索を行う

hiromasaさんが作成したWordPress用の関連投稿表示プラグインWordPress Related Post for Japanese(wp-jrelated)を利用して、各記事に過去記事から関連する記事を自動で表示しています。

この wp-jrelated が関連記事を検索する仕組みですが、おおよそ以下のとおりです。

  • Yahoo! 日本語形態素解析でコンテンツを解析し、名詞を抽出
  • 抽出された名詞を頻出順でカンマ区切りでDBに格納
  • 抽出された名詞の中から頻出する名詞トップn個を抜き出し、それを使って過去記事を like 検索
  • 関連度合いは、元記事の頻出単語が幾つ関連記事に含まれるかを計算
    その際、上位頻出単語の方が重みを持つようにランク付け
    ※このランク付け方法が中々良くできてます、ソースを読むことをオススメ

これだけで、かなりの精度を出せているので大したモノです。
しかし、単語のMD5ハッシュを取ってデータを格納しているため「WordPress」と「wordpress」、「ついった」と「ツイッタ」を別単語として扱ってしまいます。
また、今は大丈夫ですが、単語を like の or で検索しているため記事数が膨大になった時のパフォーマンスも気になります。

てなわけで、MySQL の全文検索機能を使って、さらに精度アップ&検索速度アップを狙ってみました。

MySQL で全文検索をするには対象データがわかち書きされていないといけません。
英語なんかのスペースで区切られるコンテンツでは問題が無いのですが、日本語は単語をわかち書きしないため、そのままでは全文検索できません。
なので Yahoo 形態素解析の結果から名詞だけを切り出してわかち書きしたデータを取っておき、それに fulltext インデックスをつけることにします。

大まかな作戦は以下のような感じ。

  • Yahoo! 日本語形態素解析でコンテンツを解析し、名詞を抽出
  • 抽出された名詞をスペースで区切り、DBに格納
  • 抽出された名詞の中から頻出する名詞トップn個を抜き出し、それを使って過去記事を match 検索
  • 関連度合いは match の結果から取得

最初は wp-jrelated が書き出した delimitar_text (","で分かち書きされている) を対象に match 検索をしてみたんですが、問題がありました。

  • 名詞の頻出数が文章の位置で表現されているため、頻出数が重みに反映されない
  • match 検索ではデフォルトで4文字以下の単語を相手にしないため、頻出単語の文字数が短いとマッチしない
    # MySQL の設定で文字数を変更できるが root 権限が必要なため、レンタルサーバでは変更は難しい

2つめの問題については delimitar_hash を対象にすればクリアできるのですが、一つ目の問題は
また、delimitar_hash を対象に検索すると、単語のゆらぎ検索もしたいという当初の目的から外れてしまいます。

と言うわけで、分かち書きデータを格納する separated_noun という列を用意して fulltext インデックスをつけることにしました。
ここでも名詞が4文字以下だった場合どうする?という問題が発生しましたが、これは4文字以上になるまで単語を base64_encode することで回避することにしました。
# base64_encode された単語についてはゆらぎ検索が適応できませんが、華麗にスルーします。

そんなわけで完成したのがこちらです。
wp-jrelated-fulltext-search.zip
# (wp_)morpheme テーブルの構造が違うので、使用する際は既存の (wp_)morpheme テーブルを DROP する必要があります。
# 内部的に SimpleXML を利用しているため、PHP5系でないと動作しません。

検索速度や精度があがったかどうかは未測定。
とりあえず、動作するようになりました。

WordPress Related Post for Japanese で全文検索を行う」への10件のフィードバック

  1. matz

    こちらには初めまして、

    プラグインの有効化ができずほとほと困っております。
    WPのバージョンは2.8.4ですが、それ以前(確か2.7代)から同様の症状でした。

    エラーメッセージは
    Parse error: syntax error, unexpected ‘=’, expecting ‘)’ in /****/wp-content/plugins/wp-jrelated-fulltext-search/wp-jrelated.fulltext-search.php on line 1050

    で、1050行目のfunction echoAdmin(&$result = null, &$messages = array()) { だけを見ても・・・・・でして。

    何らか打開策に繋がるコメントだけでもいただけると幸いでございます。

    返信
    1. をかもと 投稿作成者

      matz さん、はじめまして。

      サーバの PHP のバージョンはいくつでしょうか?
      私は PHP Ver 5.2.10 でしかテストしてないので、ひょっとすると PHP のバージョンに依存するエラーなのかもしれません。

      あと、他のプラグインをすべて停止して、このプラグインだけ有効な状態でも同じエラーが発生するかも確認してみてください。
      それでエラーが発生しないようであれば、どれかのプラグインとの相性問題かもしれません。

      返信
      1. matz

        をかもとさん、ご返答いただきありがとうございます。

        取り急ぎPHP4→5にしてみましたが、変わらずでした。。

        プラグインの相性は疑ってみて、一度試しているのですが・・ 再度確認してみます。

        わざわざありがとうございました、

        と、書いた後に管理画面に戻ってみたら有効化されていました!
        利用させて頂きます、ありがとうございました!

        返信
        1. をかもと 投稿作成者

          matz さん、どもです。

          このプラグインでは SimpleXML を利用しているため、PHP5系が必要になります。
          あとで、本文にも追記しておきますね。

          返信
  2. ピンバック: orioa » links for 2009-06-26

  3. ピンバック: WordPress用の関連投稿表示プラグインを変更 ? 魚眼れんず

  4. yutaka

    これは、WordPress Related Post from Refererプラグインとの入れ替えって事ですか?
    それとも全く別のものなの 😥

    返信
    1. をかもと 投稿作成者

      yutaka さん、どもです。

      これは、WordPress Related Post from Refererプラグインとの入れ替えって事ですか?
      それとも全く別のものなの 😥

      “WordPress Related Post from Referer” とは、別物です。”WordPress Related Post for Japanese” の改造版。
      ただし、これを使うと形態素解析データを保持するテーブルの構造が変わるため、”WordPress Related Post from Referer” が使えなくなります。

      返信
  5. ひろまさ

    解説、どうもありがとうございました! 😮

    そうなんです、like (「”京都”で”東京都”がヒット問題」があるので hash する)だとゆらげないんですよね。。
    fulltext の重み取得、速くて良さそうですね〜。というか、インデックスつくってるので絶対速いですよね(笑)
    時間ができたらローカルの同じデータで、2つのアルゴリズムの違いとか見てみたいと思います!

    ところでところで、レンタルサーバにはいれれないので直接関係はしないのですが、まえまえから気になっている、、senna。
    形態素もしてくれる fulltext なんですがご存じでしょうか。

     http://qwik.jp/senna/FrontPageJ.html

    これ専用サーバだといれれるなぁ、とかさきほど思っていました。 🙂

    返信
    1. をかもと 投稿作成者

      ひろまささん、どもです。

      そうなんです、like (「”京都”で”東京都”がヒット問題」があるので hash する)だとゆらげないんですよね。。
      fulltext の重み取得、速くて良さそうですね〜。というか、インデックスつくってるので絶対速いですよね(笑)

      そうなんですよね。like には、その問題があります。
      Match だと大丈夫なんだけど、今度は最低文字数の問題が…てなわけで私も一部 base64_encode しました。

      Mecab とか Senna とかは使ってみたいです。

      返信

コメントを残す

メールアドレスが公開されることはありません。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください