はじめての DynamicMTML #08 - MTSearchEntries (4) MTSplitVars を組み合わせて複数ワードのAND検索
前回は MTSearchEntries タグと MTSplitVars タグを使って複数のキーワードを OR 検索する方法を紹介しました。
今回は、AND 検索をする方法を紹介します。なお、前回の OR 検索の記事をお読みいただいている前提で進めます。
今回のテンプレートの仕様
AND 検索以外は、前回の記事と同様です。
- 検索ワードはキーワード欄にカンマ区切りで指定する
- 複数のキーワードは AND 検索
- 現在のブログ内のブログ記事から検索する
- 最新5件を表示する
- 現在のブログ記事を除く
結果をイメージするために
今回のサンプルに使ったブログには、次のような10本のブログ記事が公開されているとします。
この中で「つめ」「dynamicmtml」という2つのキーワードを両方含むブログ記事を、最大5本リストアップするようにします。「つめ」というキーワードは、普通ではあり得ませんが、結果を意図的に操作するためですので気にしないでください。
ブログ記事#10 : これはブログ「はじめての DynamicMTML ブログ」の10番目の記事です。
ブログ記事#09 : これはブログ「はじめての DynamicMTML ブログ」の9番目の記事です。
ブログ記事#08 : これはブログ「はじめての DynamicMTML ブログ」の8番目の記事です。
ブログ記事#07 : これはブログ「はじめての DynamicMTML ブログ」の7番目の記事です。
ブログ記事#06 : これはブログ「はじめての DynamicMTML ブログ」の6番目の記事です。
ブログ記事#05 : これはブログ「はじめての DynamicMTML ブログ」の5つめの記事です。
ブログ記事#04 : これはブログ「はじめての DynamicMTML ブログ」の4つめの記事です。
ブログ記事#03 : 3つ目の記事です。
ブログ記事#02 : これはブログ「はじめての DynamicMTML ブログ」の2つめの記事です。
ブログ記事#01 : これはブログ「はじめての DynamicMTML ブログ」の1つめの記事です。
赤字になっているブログ記事の「01, 02, 04, 05」が検索結果になります。
完成したコード
今回の記事の完成版のコードは次のようになります。強調されている部分が、前回の OR 検索との変更点になります。
※2012-01-23 MTLoop のところを少し修正しました。
<$mtml tag='mt:SetVars'$>
blog_id=<$mt:BlogID$>
entry_id=<$mt:EntryID$>
keywords=<$mt:EntryKeywords$>
keywords_length=<$mt:EntryKeywords regex_replace="/[^,]|\s/g","" cat="," count_characters="1"$>
limit=5
<$mtml tag='/mt:SetVars'$>
<mt:DynamicMTML>
<mt:SplitVars name="keyword" text="$keywords">
<$mt:Var name="__counter__" setvar="split_counter"$>
<$mt:Var name="keyword" trim="1" regex_replace="/\s| /g","%" setvar="keyword"$>
<mt:SearchEntries query="$keyword" blog_id="$blog_id" not_entry_id="$entry_id">
<$mt:EntryDate format="%Y%m%d%H%M%S" setvar="date"$>
<mt:If name="split_counter" eq="1">
<mt:SetVarBlock name="entries" key="$date">
<li><a href="<$mt:EntryPermalink$>"><$mt:EntryTitle$></a></li>
</mt:SetVarBlock>
<$mt:SetVar name="match_count" key="$date" value="1"$>
<mt:Else>
<mt:If name="entries" key="$date">
<$mt:SetVar name="match_count" key="$date" op="++"$>
</mt:If>
</mt:If>
</mt:SearchEntries>
<mt:If name="split_counter" eq="$keywords_length">
<mt:Loop name="entries">
<mt:If name="match_count" key="$__key__" eq="$keywords_length">
<$mt:SetVar name="result" key="$__key__" value="$__value__"$>
</mt:If>
</mt:Loop>
<mt:Loop name="result" sort_by="key reverse">
<mt:If name="__counter__" eq="1">
<ul>
</mt:If>
<mt:If name="__counter__" le="$limit">
<mt:Var name="__value__">
</mt:If>
<mt:If name="__counter__" eq="$limit">
</ul>
</mt:If>
</mt:Loop>
</mt:If>
</mt:SplitVars>
</mt:DynamicMTML>
以下、変更されている部分を見ていきます。
MTSplitVars のループの1回目とそれ以外で分岐する
<mt:If name="split_counter" eq="1">
<mt:SetVarBlock name="entries" key="$date">
<li><a href="<$mt:EntryPermalink$>"><$mt:EntryTitle$></a></li>
</mt:SetVarBlock>
<$mt:SetVar name="match_count" key="$date" value="1"$>
<mt:Else>
<mt:If name="entries" key="$date">
<$mt:SetVar name="match_count" key="$date" op="++"$>
</mt:If>
</mt:If>
MTSearchEntries タグの中で、MTSplitVars のループの1回目とそれ以外とで動作を分岐します。変数 split_counter には、MTSplitVars タグのループの回数がセットされています(1から始まる)。この split_counter は、MTSplitVars タグの先頭で初期化してある必要があります(前回記事参照)。
最初のループ(1つめのキーワード)
MTSplitVars タグの最初のループ、つまり1つめのキーワードについては、そのまま MTSearchEntries を回しています。
ここでは、投稿日時(年月日時分秒)がキーであるハッシュ変数 entries に値を入れていきます。今回は AND 検索なので、最終的な検索結果は、この変数 entries から絞り込まれることになります。
さらに、同様に投稿日時がキーであるハッシュ変数 match_entries の各値に 1 をセットします。この entries と match_entries のキーを同じにしておくことがポイントとなります(後述)。
※これ以降の解説を読むと、ここでセットするキーは、投稿日時よりもエントリーID の方がしっくりくるのですが、最終的に出力するときに、投稿日時でソートするためにそのようにしています。
2回目以降のループ(2つめのキーワード以降)
MTSplitVars タグの2回目のループ、つまり2つめのキーワード以降で、1つめのキーワードの検索結果の中にそのブログ記事があるかどうかを調べます。
<mt:If name="entries" key="$date">
<$mt:SetVar name="match_count" key="$date" op="++"$>
</mt:If>
もし該当するブログ記事が既に変数 entries にセットされているのであれば、変数 match_entries の値をインクリメント(1増やす)します。
つまり、この変数 match_entries の各キーに対応する値が、キーワードにマッチした回数ということになります。
キーワードにマッチした回数がキーワード数と同じものを出力する
最後に、MTLoop を2回まわしています。
1つめの MTLoop で変数 entries について、ループ中のブログ記事のキーワードにマッチした回数がキーワード数と同じもの、つまりすべてのキーワードにマッチしたものだけを、ハッシュ変数 result にセットします。このとき、ハッシュ変数 result の key と value は、元のハッシュ変数 entries の $__key__ と $__value__ を引き継ぎます。
<mt:Loop name="entries">
<mt:If name="match_count" key="$__key__" eq="$keywords_length">
<$mt:SetVar name="result" key="$__key__" value="$__value__"$>
</mt:If>
</mt:Loop>
ここで見て分かるように、entries と match_entries のキーを同じにしておけば、entries のループの時に、キー( __key__ )をそのまま match_entries のキーとして渡すことで、そのブログ記事のマッチ回数を調べることができます。
このマッチ回数がキーワード数(keyword_length : 先頭の MTSetVars でセット。こちらを参照)と同じであれば AND 検索の結果に該当(すべてのキーワードがマッチ)することになります。
そして、2つめの MTLoop で、先頭の MTSetVars でセットした limit の数だけ出力します。
以上です。複雑ですね。
「はじめての DynamicMTML」に関連する記事
- はじめての DynamicMTML #13 - 指定期間内の記事をリストアップする
- はじめての DynamicMTML #12 - 静的ファイルの PHP を実行する
- はじめての DynamicMTML #11 - MT タグの中で PHP を実行する
- はじめての DynamicMTML #10 - クエリを処理する4つのテンプレートタグ
- はじめての DynamicMTML #09 - MTSearchEntries (5) MTReferralKeywords で検索サイトからの流入に対する関連記事を表示する
- はじめての DynamicMTML #08 - MTSearchEntries (4) MTSplitVars を組み合わせて複数ワードのAND検索
- はじめての DynamicMTML #07 - MTSearchEntries (3) MTSplitVars を組み合わせて複数ワードのOR検索
- はじめての DynamicMTML #06 - MTSearchEntries (2) 基本的な使い方
- はじめての DynamicMTML #05 - MTSearchEntries (1) 動的にブログ記事を検索する
- はじめての DynamicMTML #04 - ログイン状態で分岐する MTIfLogin
- はじめての DynamicMTML #03 - スタティックパブリッシングで DynamicMTML を使う書き方
- はじめての DynamicMTML #02 - .htaccess と .mtview.php の役割
- はじめての DynamicMTML #01 - 準備とインストール
トラックバック
The trackback URL is "".



コメントする