MT の検索結果をページ処理(Page Navigation)する方法 - MTPaginate 編

Movable Type で記事が数百件オーダーになってくると、検索結果のページの重さが気になってきます。特に気になるのが検索キーワードによっては、100 件近くの記事がヒットして検索結果ページのコンテンツ量が多すぎて嫌になる点。

手っ取り早く解消するには、Movable Type にページ処理機能を追加してくれる MTPaginate プラグインを導入することで実現可能です。ちなみにページ処理とは、Google や Yahoo! の検索結果ページで,

google.jpg

のようにページナビゲーションを表示する処理のことをいいます。コンテンツ量が増えてきた方は導入されてみては如何でしょうか?

- スポンサーリンク -

さて、導入方法について説明します。

  1. MTPaginate プラグインを手に入れる MT Extensions というサイトから MTPaginate をダウンロードします。画面の上の方にリンクされている download という部分からプラグインをダウンロードして保存します。現時点での最新版は 1.26 のようです。
  2. ダウンロードした MTPaginate プラグインをサーバにアップロード ダウンロードしたプラグインを Movable Type をインストールした先の plugins というディレクトリ内に FTP します。その他のプラグインの設置方法と何ら代わりはありません。
  3. 検索結果ページのテンプレート(search_templates/default.tmpl)を編集 Movable Type の検索結果ページのテンプレートは、search_templates/default.tmpl になります。MT 3.2 でも検索結果ページのテンプレートは直接エディタによる編集でしか手がありません。日本語を扱うので、EUC や Unicode が扱えるエディタで編集して、素の文字コードのまま保存してください。

    以下のようにコードを追加下さい。(黒色の部分が素のコードで、赤色の部分が追加分です)

    <MTPaginate mode="cgi">
    <MTPaginateIfMultiplePages>
    <div style="text-align: center;">
    Results <b><MTPaginateTopSection></b> - <b><MTPaginateBottomSection></b> of <MTPaginateNumSections>: <MTPaginateIfAllPages_><b>[ ALL ]</b><MTPaginateElse_><a href="<$MTPaginateAllPagesLink$>">show all</a></MTPaginateIfAllPages_>
    <MTPaginateIfPreviousPage_><a href="<MTPaginatePreviousPageLink>"><b><</b></a><MTPaginateElse_></MTPaginateIfPreviousPage_> <MTPaginateNavigator separator="  " format="%d" format_current="<b>[ %d ]</b>"> <MTPaginateIfNextPage_><a href="<MTPaginateNextPageLink>"><b>></b></a><MTPaginateElse_></MTPaginateIfNextPage_>
    </div>
    </MTPaginateIfMultiplePages>

    <MTSearchResults> <MTBlogResultHeader>
    <h2><MT_TRANS phrase="Search Results from"> <$MTBlogName$></h2>
    </MTBlogResultHeader> <h3><a href="<$MTEntryPermalink$>"><$MTEntryTitle$></a></h3>
    <p><$MTEntryExcerpt$> <$MTEntryEditLink$></p>
    <p class="posted"><MT_TRANS phrase="Posted in"> <$MTBlogName$> <MT_TRANS phrase="on"> <$MTEntryDate$></p> <MTPaginateSectionBreak> </MTSearchResults>
    <MTPaginateIfMultiplePages>
    <MTPaginateNavigator separator="  " format="%d" format_current="<b>[ %d ]</b>">
    </MTPaginateIfMultiplePages>

    以上で、ページナビゲーションが検索結果の上に表示されていると思います。下にも同じナビゲーションを表示したければ、

    <MTPaginateIfMultiplePages>
    <MTPaginateNavigator separator="  " format="%d" format_current="<b>[ %d ]</b>">
    </MTPaginateIfMultiplePages>
    と記述すれば良いだけです。検索結果ページに以下のようなナビゲーションが表示されるようになると思います。
    search.jpg

ちなみに、<MTPaginateTopSection>や< MTPaginateBottomSection>あたりのタグは1回しか記述できなかったりと色々な制約もあったりします。残念ながら MTPaginate の日本語解説で詳しいところはあまり見かけないので、本家サイトの解説を一生懸命読んでみることをオススメします。php で MTPaginate を使う場合は若干記述が違いますのでご注意を。

さて、ちなみに MTPaginate の使い道ですが、本当はカテゴリ毎のページなどの静的なページに対して使用するプラグインです。その理由は、取得した全結果データからページ処理をちまちま作るので処理が重いためです。その他のページでの利用方法については、他のブログの記事に譲ります。

MTPaginate は検索結果が 200 件になったならば、その 200 件と言う数字からナビゲーションを作成し、200 件のデータから必要な部分を表示なんて処理を行っています。なので、本当の意味でのページ処理とは違います。

実は、検索結果の処理が重い理由は Movable Type の検索の実装方法にも問題がありまして、Movable Type の検索の実装方法は大まかにこんな処理になってます。

  1. エントリーのデータを取りあえず全件取得
  2. 正規表現を用いて、title, text, text_more, keywords, (comments) と検索ワードのマッチング処理
  3. 正規表現で条件に合致したもののみを結果に表示

これは、MT::ObjectDriver::DBI に like 句による条件を SQL に記述できない仕様(少なくとも現状のコードは。)および正規表現により、曖昧検索を可能にするためのトレードオフ的な仕様に起因するものと思われます。

この記事のタイトルですが、わざと意味ありげに MTPaginate 編としていますが、MT::ObjectDriver::DBI::mysql とかを Hack することで、like 句をサポートさせ、本当の意味でのページ処理を実装することで、かなり高速な検索機能を実現することが可能です。

その方法については、もう少しプログラムをお見せできる状態にまとめてから公開しようと思います。

- スポンサーリンク -