AllKeywords PluginとMT-XSearchの連携
AllKeywords Pluginは、エントリーのキーワード部分をハンドリングするための機能を追加するだけでなく、MT-XSearchと連携して軽量なキーワードサーチを行うための機能も持っている。キーワードサーチはMovable Typeに付属しているmt-search.cgiを改造することもでも実現できるが、改造してしまうと他の用途に利用できないというデメリットもある。一方、MT-XSearch*1はさまざまな検索サービスを追加できるフレームワークで、どのような検索を実現するかはプラグインとして分離することができる。AllKeywords Pluginはその一例となっている。
このエントリーではAllKeywords PluginとMT-XSearchとの連携方法とその高速化手法について述べる。
*1 Tim Appnelの作。昨年のDevelopper's Contestの受賞作の一部で、Movable Typeに拡張性のある検索サービスを追加するためのフレームワーク。運悪くmovabletype.org : Developer's Contest Plugin Pack: 2004のページからplugin packへのリンクがなくなっており、Appnelも(パッチは公開しているが)公開していないので現在Webでは入手不能。公開してくれよとは言っているのだが…。そういうわけで残念ながらAllKeywords Pluginの連携機能の効果は限定的なものとなる。
2005-06-11追記: MT-XSearch自体はDownload mt-plus | Appnel Internet Solutionsから入手できる。
連携方法
すでにAllKeywords Pluginはインストール済みとする。
- MT-XSearchをインストールする。具体的には
プラグインパッケージに含まれるMT-XSearch0.3.zipmt-plus-1.01.zipをアンパックしてその中のmt-xsearch.cgi、plugins/mt-xsearch.pl、extlib/MT/XSearch.pmをそれぞれ適切なディレクトリにアップロードする。mt-xsearch.cgiはCGIとして実行できるように実行権限を与える必要がある。 - mt-xsearch.cgiはそのままでは日本語がうまくハンドリングできないので、以下のパッチを当てる。
--- mt-xsearch.cgi.bak Fri Aug 27 12:06:24 2004 +++ mt-xsearch.cgi Sat Jun 11 02:58:33 2005 @@ -41,7 +41,8 @@ $ctx->stash('CGI',$q); my $out = $tmpl->build($ctx) or die "Building search template failed: ".$tmpl->errstr; - print $q->header.$out; + my $charset = $mt->{cfg}->PublishCharset; + print $q->header(-charset=>$charset).$out; }; if ($@) { print "Content-Type: text/html\n\n"; - 2005-06-11追記: plugins/mt-xsearch.plはそのままではdivision by zeroエラーが起きるので、以下のパッチを当てる。
--- plugins/mt-xsearch.pl.bak Sat May 14 06:01:19 2005 +++ plugins/mt-xsearch.pl Sat Jun 11 00:31:39 2005 @@ -63,7 +63,7 @@ my $pages = $limit ? ($count-($count % $limit)) / $limit : 1; $pages += ($limit && $count % $limit) ? 1 : 0; my $offset = $xsearch->args->{offset} || 0; - my $current = $offset / $limit + 1; + my $current = $limit ? ($offset / $limit + 1) : 1; $ctx->stash('MT::XSearch::current_page',$current); $ctx->stash('MT::XSearch::pages',$pages); my $builder = $ctx->stash('builder'); - 「XSearch AllKeywords」という名前のテンプレートモジュールを作り、例えば以下のように記述する。
<html> <body> <form method="get" action="<$MTCGIPath$>mt-xsearch.cgi"> <input type="hidden" name="blog_id" value="<$MTBlogID$>" /> <input type="hidden" name="search_key" value="AllKeywords" /> <label for="search" accesskey="4">Search this site:</label> <input id="search" name="search" size="20" value="<$MTSearchString decode_url="1" encode_html="1"$>" /> <input type="submit" value="Search" /> </form> <MTSearchResults> <MTSearchHeader> Results found: <$MTSearchResultCount$> <ol> </MTSearchHeader> <li><a href="<$MTEntryLink$>"><$MTEntryTitle$></a></li> <MTSearchFooter> </ol> <p>Searched on: <em><$MTSearchString decode_url="1"$></em></p> </MTSearchFooter> </MTSearchResults> <MTNoSearch><p>No search performed.</p></MTNoSearch> <MTNoSearchResults><p>Nothing found.</p></MTNoSearchResults> </body> </html>
テンプレートモジュールは好きなようにカスタマイズできる。
使い方
インデックステンプレートやアーカイブテンプレートに以下のように追加すれば、キーワード検索用のフォームを作ることができる。
<form method="get" action="<$MTCGIPath$>mt-xsearch.cgi"> <input type="hidden" name="blog_id" value="<$MTBlogID$>" /> <input type="hidden" name="search_key" value="AllKeywords" /> <label for="search" accesskey="4">Search this site:</label> <input id="search" name="search" size="20" value="<$MTSearchString decode_url="1" encode_html="1"$>" /> <input type="submit" value="Search" /> </form>
また、以下のようにフォームを生成せずに特定のキーワードの検索結果へのリンクを作ることもできる。
<$MTCGIPath$>mt-xsearch.cgi?blog_id=<$MTBlogID$>&search_key=AllKeywords&search=Blog
.htaccessに以下のように記述すれば、「http://blog.your.domain/tag/Keyword」のように簡便なURLで特定のキーワードの検索結果を得られる。
RewriteEngine on RewriteRule ^tag/(.*)$ /mt/mt-xsearch.cgi?blog_id=1&search_key=AllKeywords&search=$1 [QSA,L]
以下は2005-06-11に追記したものです。
高速化の方法
上記で説明した方法ではリクエストのたびにCGIを起動し、検索結果を取得して表示しているため、動作が遅いことは否定できない。しかしタグには滅多に変更がないことを前提にするなら、一定期間検索結果をキャッシュしたり、データの転送を抑制したりすることで大幅な高速化が可能になる。
ここでは手っ取り早くCGI::Cacheを使って高速化を実現する方法を紹介する。具体的には、検索結果を一定時間(例では1時間)キャッシュし、なおかつHTTP HeaderのLast-Modifiedにキャッシュした時刻を格納して返す。つまり、以下の二つの効果が期待される。
- キャッシュを作成してから一定時間内は再検索しないことによる負荷の軽減
- この期間内に二回以上アクセスするブラウザには304 Not Modifiedを返すことによる、データ転送の削減
方法は単純で、CPANからCGI::Cacheモジュールをインストールし、「連携方法」の2.で示したパッチの代わりに以下のパッチをmt-xsearch.cgiに適用するだけでよい。赤字で示した部分はそれぞれ「キャッシュの作成場所」「キャッシュの生存期間」を表す。下記の例ではそれぞれ「mt-xsearch.cgiのあるディレクトリの直下のcacheディレクトリ」「1時間(=3600秒)」を指定してあるので必要に応じて変更するとよい。
--- mt-xsearch.cgi.bak Fri Aug 27 12:06:24 2004
+++ mt-xsearch.cgi Sat Jun 11 03:44:32 2005
@@ -17,6 +17,7 @@
}
use CGI;
+use CGI::Cache;
use MT;
use MT::ConfigMgr;
use MT::Template;
@@ -27,10 +28,13 @@
my $mt = MT->new( Config => $MT_DIR . 'mt.cfg', Directory => $MT_DIR )
or die MT->errstr;
my $q = new CGI;
+ CGI::Cache::setup({ cache_options => { cache_root => './cache', default_expires_in => 3600 } });
my $blog_id = $q->param('blog_id') or
die "Missing parameter blog_id";
my $key = $q->param('search_key') or
die "Missing parameter key";
+ CGI::Cache::set_key($q->Vars);
+ CGI::Cache::start() or exit;
my $search = MT::XSearch->execute($q);
my $tmpl = MT::Template->load( {
name=>'XSearch '.$key,
@@ -41,7 +45,14 @@
$ctx->stash('CGI',$q);
my $out = $tmpl->build($ctx)
or die "Building search template failed: ".$tmpl->errstr;
- print $q->header.$out;
+ my $charset = $mt->{cfg}->PublishCharset;
+ my @m = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
+ my @w = qw(Sun Mon Tue Wed Thu Fri Sat);
+ my ($sec, $min, $hour, $mday, $mon, $year, $wday) = gmtime(time);
+ my $now = sprintf("%3s, %02d %3s %04d %02d:%02d:%02d GMT",
+ $w[$wday], $mday, $m[$mon], $year+1900, $hour, $min, $sec);
+ print $q->header(-charset=>$charset,-Last_Modified=>$now).$out;
+ CGI::Cache::stop();
};
if ($@) {
print "Content-Type: text/html\n\n";
このエントリーのトラックバックURL: http://as-is.net/mt/mt-tb.cgi/256
どうにも諦めきれずにファイル名を推測して総当りをかけたところ、予想が当たって見つけてしまったので報告しておきます。認証のかかっていない WWW に公開されているので、良いだろうということで。
http://www.timaoutloud.org/code/mt/MT-XSearch.tar.gz
これに 0.31 のパッチを当てたのち、ogawa さんの diff を当てて四畳半フォークソノミーの実現に向けた準備は整いました。私にとって最後の課題は「既存のカテゴリー名をキーワードとして設定し直す」ことです。この問題が解決できればすぐにでもカテゴリを廃止して乗り換えたいと思っています。このサイトでは過去のエントリについてもキーワードが設定されているように見受けられますが、どのようにして既存のカテゴリー名をキーワードとして設定し直す機能を実現したのか、是非教えていただきたいです。
(エントリ中に extlib/MT/App/XSearch.pm をアップロードする旨の記述がありますが、私が入手した XSearch のアーカイブでは extlib/MT/XSearch.pm でした。)
:-)
見つけてしまいましたか。私がTimから送ってもらったバージョンが0.32なので最新のが置かれているわけではないみたいですね。XSearch.pmのアップロード場所は私の勘違いでした。
私のところではまだ既存のカテゴリー名をキーワードとして設定し直してはいないです。実は↓あたりに適当に作りかけてはあるのですが、動作確認はしていません。というかとりあえず書いてみただけのバージョンでパーザが通るかどうかすら確認していません。
http://code.as-is.net/svn/public/mt-cats2keywords/trunk/mt-cats2keywords.cgi
なんと!
どうやら私の早とちりだったようです、失礼しました。早速 mt-cats2keywords.cgi を試してみたところ、私の環境では問題なく移行することができました。面倒な作業を楽に処理できて嬉しいです。
では、今後もひっそりと AllKeywords Plugin による四畳半フォークソノミーの実現に向けた活動を見守ってゆきたいと思います。