Jul 1, 2005

TagwireとMT-XSearchによる動的タグアーカイブ

Tags Pluginがサポートする静的なタグ(カテゴリー)アーカイブの代わりに、Tagwire PluginはTim AppnelのMT-XSearchを用いた動的タグアーカイブ機能を実現しています。一般的に言って動的タグアーカイブは、静的アーカイブに比べて生成速度の点で劣りますが、より柔軟なアーカイブ生成がサポートできるという望ましい性質も持っています。例えば、Tagwireでは指定された複数のタグを持つエントリーだけをリストする機能を提供しています。

このエントリーでは、Tagwire PluginをMT-XSearchと組み合わせて動的タグアーカイブを実現する方法とその高速化手法について述べます。

セットアップ方法

すでにTagwire Pluginはインストール済みとします。

  1. MT-XSearchをインストール:
    まず、mt-plus-1.01.zipをDownload mt-plus | Appnel Internet Solutionsからダウンロードし、パッケージに含まれている以下のファイルをMovable Typeのディレクトリにアップロードないしコピーします。
    • mt-xsearch.cgi (実行権限が必要)
    • plugins/mt-xsearch.pl
    • extlib/MT/XSearch.pm
  2. mt-xsearch.cgiとplugins/mt-xsearch.plに以下のパッチを当てます。これはMT-XSearchの多言語対応とバグフィックスのためで、将来のMT-Plus/MT-XSearchのリリースではこのパッチ内容が反映されている可能性があります。
    --- 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";
    
    --- 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');
    
  3. 「XSearch Tagwire」という名前のテンプレートモジュールを作り、以下のように記述します。
    <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="Tagwire" />
    <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="Tagwire" />
<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>

タグアーカイブリンク:

フォームを生成せずに特定のキーワードの検索結果へのリンクを直接作ることもできます。

<MTEntryTags glue=", ">
<a href="<$MTCGIPath$>mt-xsearch.cgi?blog_id=<$MTBlogID$>&search_key=Tagwire&search=<$MTTag encode_url="1"$>"><$MTTag$></a>
</MTEntryTags>

より簡便なタグアーカイブリンク:

「http://my.host.tld/tag/Tag」のように簡便な形式のURLでタグアーカイブにアクセスできるようにするには、以下のように.htaccessに追加します。

RewriteEngine on
RewriteRule ^tag/(.*)$ /mt/mt-xsearch.cgi?blog_id=1&search_key=Tagwire&search=$1 [QSA,L]

この設定を行っておけば、タグアーカイブへのリンクは以下のように書くことができます。

<MTEntryTags glue=", ">
<a href="<$MTBlogURL$>tag/<$MTTag encode_url="1"$>"><$MTTag$></a>
</MTEntryTags>

詳しいオプション

タグ検索フォームのフィールド、もしくはタグアーカイブリンクのQuery Stringに追加可能なオプションは以下に示す通りです。

blog_id (REQUIRED)
検索対象となるブログIDを指定します。
search_key (REQUIRED)
"Tagwire"という固定の文字列を指定してください。
search (REQUIRED)*1
URLエンコーディングされた検索文字列を指定します。delimiter(区切り文字)で区切られた一個以上のタグを指定できます。複数のタグを指定した場合には、MT-XSearchはそれらすべてをタグとして持つエントリーのリストを生成します。
delimiter*1
検索文字列のdelimiter(区切り文字)を指定します。デフォルトのdelimiterは空白文字(URLエンコーディングでは%20または+)です。
case_sensitive [0 | 1]
キーワードの大文字・小文字を区別するかどうかを指定します。デフォルトでは区別します(case_sensitive="1")。
sort_order [ascend | descend]
リストアップする順序を昇順(ascend)か降順(descend)かを選択します。デフォルトでは降順(descend)です。

*1 searchオプションとdelimiterオプションの関係が分かりやすいように以下では例を挙げます:

  • searchに"movable+type"を指定し、delimiterを省略した場合:
    "movable"と"type"というタグを持つエントリーのリストが生成されます。
  • searchに"movable,type"を指定し、delimiterに","を指定した場合:
    上と同様、"movable"と"type"というタグを持つエントリーのリストが生成されます。
  • searchに"movable+type,plugin"を指定し、delimiterに","を指定した場合:
    "movable type"と"plugin"というタグを持つエントリーのリストが生成されます。
  • searchに"movable+type,plugin"を指定し、delimiterを省略した場合:
    "movable"と"type,plugin"というタグを持つエントリーのリストが生成されます。

少し進んだ話題: CGI::Cache enabled MT-XSearch

上記で説明した方法ではタグアーカイブにアクセスするたびにCGIプロセスを起動し、DBからタグ情報を取得し、それを結果ページとして表示するため、動作が遅いことは否めません。しかし、タグには滅多に変更がないことを前提にするなら、一定期間検索結果をキャッシュしたり、データの転送を抑制したりすることで大幅なオーバーヘッドの削減が可能になります。

ここではCGI::Cacheを使った高速化方法(CGI::Cache enabled MT-XSearchと呼ぶ)を紹介します。具体的には、検索結果を一定時間(例では1時間)キャッシュし、かつHTTP HeaderのLast-Modifiedにキャッシュした時刻を格納して返します。これによって以下の二つの効果が期待されます。

  • キャッシュを作成してから一定時間内は再検索しないことによる負荷の軽減
  • この期間内に二回以上アクセスするブラウザには304 Not Modifiedを返すことによる、データ転送の削減

CGI::Cache enabled MT-XSearchを実現するには、CPANからCGI::Cacheモジュールをインストールし、以下のパッチをmt-xsearch.cgiに適用します。

--- 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";

赤字で示した部分はそれぞれ「キャッシュの作成場所」「キャッシュの生存期間」を表します。上記の例ではそれぞれ「mt-xsearch.cgiのあるディレクトリの直下のcacheディレクトリ」「1時間(=3600秒)」を指定してあります。

About Me

My Photo

つくばで働く研究者

Total Pageviews

Amazon

Copyright 2012 Ogawa::Buzz | Powered by Blogger
Design by Web2feel | Blogger Template by NewBloggerThemes.com