はじめに
Data APIを使うと、MovableType管理画面本体と切り離しが難しくなるので・・最悪公開サーバから編集サーバをみるようにとか・・
いままで使用していなかったが、とりあえず試すことに・・・
コンテンツデータを使って、1000件以上のデータを検索することの想定です。
1000件以下であれば、javascript用のデータをMovableTypeから作ったほうが・・・
javascript用のデータでも、月別アーカイブだったり、カテゴリアーカイブ化でjavascript用のデータをつくって
ごまかしてきましたが・・・
準備
MovableTypeをインストールしたディレクトリ内で、mt-data-api.cgiを探しパーミッションが設定されているか確認する。
mt-data-api.cgiのパーミッションを755など、サーバーに合わせて設定する。
筆者は、なるべく、最小でパーミッションを設定しているので、下記に実行権限与えていません。
mt-search.cgi
mt-comments.cgi
mt-cdsearch.cgi
mt-data-api.cgi
MovableType7は下記も・・
mt-atom.cgi
mt-feed.cgi
mt-ftsearch.cgi
mt-tb.cgi
mt-xmlrpc.cgi
MovableType管理画面設定のWebサービス設定から下記にチェックをする・・・
あとセキュリティ対策で・・
今回は、外部と連携しないので自サーバーからのみ許可する感じ・・
ただ、デバック中は、offのがよいです。
この場合は、公開、編集サーバーが同一の場合です。別々の場合は、2つドメインを許可するとか・・
SetEnvIf Referer "^https://www\.xxx\.xxx\.jp/" ref_ok
order deny,allow
deny from all
allow from env=ref_ok
Data APIの仕様・・を
基本、RESTful API(REST API)ぽいので・・・なんとかなりそう・・
MTのJavaScript SDKもあるようですが・・今回はじか書きで・・
下記のSearch
https://movabletype.github.io/mt-docs-data-api-reference/v6.html#tag/Search
下記で動作確認・・
/mt-data-api.cgi/v6/search?IncludeBlogs=ブログID&cdSearch=1&search=検索したいワード
うう。。指定したサイトのコンテンツタイプ全部でるじゃんか・・・コンテンツタイプの指定が・・見当たらない・・
ContentData.pmのソース眺めて、SearchContentTypes、SearchContentTypeIDってあったから・・・
下記で動作確認、うううごいた
/mt-data-api.cgi/v6/search?IncludeBlogs=ブログID&cdSearch=1&SearchContentTypes=コンテンツタイプのID&search=検索したいワード
これで何となく、手入力で確認できたので・・・
javascript書いてみる・・
下記は、MTで再構築するHTMLテンプレートに入れ込む感じ?
バージョンを固定したい場合直接数字を・・・
var searchkey = "";
var DATA_API_PATH = "<mt:CGIPath><mt:DataAPIScript>";
var DATA_API_VER = "<mt:DataAPIVersion>";
var BLOG_ID = "<mt:BlogID>";
var CONTENTTYPE_ID = "23"; //目標のID
下記は、jsファイル化して呼び出す共通
json.totalResultsとかで最大件数が入ってくるので、limitとかoffsetでページ制御もできるかと・・
function xxxxSearch(){
$('#content_data').empty();
if(searchkey) {
$.ajax({
url: DATA_API_PATH + "/v"+DATA_API_VER+"/search?IncludeBlogs="+BLOG_ID +"&cdSearch=1&SearchContentTypes="+CONTENTTYPE_ID+"&search="+searchkey,
type: "GET",
dataType: "json",
}).done(function(json){
recs = json.items;
$.each(recs,function(key,item){
var li_tag =
'<div>' +
'<p>'+item.data[0].data+'</p>' +
'<p>'+item.data[1].data+'</p>' +
'<p>'+item.data[2].data+'</p>' +
'</div>';
$('#content_data').append(li_tag);
});
});
}
}
xxxxSearch();
$('#search_btn').on("click", function(){
searchkey = $('#searchkey').val();
xxxxSearch();
});
下記はMTのテンプレートに入れる部分
<form>
<input type="text" name="searchkey" id="searchkey">
<button type="button" id="search_btn">検索</button>
</form>
<ul id="content_data">
</ul>
ページャー付けた感じ・・
あと、記事書きながら・・limitとか調べてたから・・下記にSearchContentTypesってあった・・・
https://www.movabletype.jp/documentation/mt8/designers-guide/search/contenttype/contenttype-search-page/
SearchContentTypesは、AND ORが使えるので・・
あくまでも全文検索かなぁ・・ページャーとかなしでいいのであれば、全文検索と複合検索はできそう・・
MTの検索機能のlimitとoffsetを使って・・このページだったら、このoffsetからlimit件数までという処理
1個目のajaxは入力されたキーワードで最大何件あるかをページャー用に調べて、展開する形・・・
このままだと、idが重なる場合があるので配慮がいります。。
$(function() {
var LIST_LIMIT = 10;
var NOWPAGE = "";
var start,end;
var searchkey = "";
var DATA_API_PATH = "<mt:CGIPath><mt:DataAPIScript>";
var DATA_API_VER = "<mt:DataAPIVersion>";
var BLOG_ID = "<mt:BlogID>";
var CONTENTTYPE_ID = 23;
function xxxxSearch(NOWPAGE){
if(searchkey) {
$('#pager').empty();
$('#content_data').empty();
$.ajax({
url: DATA_API_PATH + "/v"+DATA_API_VER+"/search?IncludeBlogs="+BLOG_ID +"&cdSearch=1&SearchContentTypes="+CONTENTTYPE_ID+"&limit=1&search="+searchkey,
type: "GET",
dataType: "json",
}).done(function(json){
var hits = json.totalResults;
[NOWPAGE,start,end] = listpage_cal(NOWPAGE,LIST_LIMIT);
var offset = start;
var limit = LIST_LIMIT;
$.ajax({
url: DATA_API_PATH + "/v"+DATA_API_VER+"/search?IncludeBlogs="+BLOG_ID +"&cdSearch=1&SearchContentTypes="+CONTENTTYPE_ID+"&offset="+offset+"&limit="+limit+"&search="+searchkey,
type: "GET",
dataType: "json",
}).done(function(json){
recs = json.items;
$.each(recs,function(key,item){
var li_tag =
'<div>' +
'<p>'+item.data[0].data+'</p>' +
'<p>'+item.data[1].data+'</p>' +
'<p>'+item.data[2].data+'</p>' +
'</div>';
$('#content_data').append(li_tag);
});
pager = listpage_bar(NOWPAGE,hits,LIST_LIMIT);
$('#pager').append(pager);
});
});
}
}
xxxxSearch("");
$('#search_btn').on("click", function(){
searchkey = $('#searchkey').val();
xxxxSearch("");
});
function listpage_cal(page_no,limit_max)
{
var pi;
var start,end;
//ページインデックス
if(page_no == '') {
page_no = 1;
} else if(!Number.isFinite(page_no)) {
page_no = 1;
}
pi = (page_no - 1) * limit_max;
start = pi;
end = pi + limit_max;
return[page_no,start,end];
}
function listpage_bar(page_no,list_hits,limit_max)
{
var prev_one,next_one;
var end_no,st_no;
var pages_f,pre_page_a,disp_page_st,disp_page_end;
var pages;
var i,j;
var page_barstr;
page_barstr="";
prev_one = page_no - 1;
next_one = page_no + 1;
end_no = page_no * limit_max;
st_no = end_no - limit_max + 1;
if(end_no >= list_hits){
end_no = list_hits;
}
pages = Math.floor(list_hits / limit_max);
if(list_hits % limit_max) {
pages ++;
}
if(list_hits > limit_max) {
if(page_no > 1){
page_barstr = page_barstr + "<li><a href=\"javascript:void(0)\" id=\"pager_1\">先頭へ</a></li>";
page_barstr = page_barstr + "<li><a href=\"javascript:void(0)\" id=\"pager_"+prev_one+"\"> <</a></li>";
}
pages_f = Math.floor(pages / 10);
if(pages % 10) {
pages_a = 1;
} else {
pages_a = 0;
}
pre_page_f = Math.floor(page_no / 10);
if(page_no % 10) {
pre_page_a = 1;
}else{
pre_page_a = 0;
}
if(pre_page_a){
disp_page_st = pre_page_f * 10 + 1;
} else {
disp_page_st = pre_page_f * 10 - 9;
}
disp_page_end = disp_page_st + 9;
for(pg=1;pg <= pages;pg++) {
if(disp_page_end < pg){
break;
}
if(disp_page_st <= pg){
if(pg != page_no){
page_barstr = page_barstr + "<li><a href=\"javascript:void(0)\" id=\"pager_"+pg+"\">"+pg+"</a></li>";
} else {
page_barstr = page_barstr + "<li><b><a href=\"javascript:void(0)\" class=\"active\">"+pg+"</a></b></li>";
}
}
}
if(page_no < pages) {
page_barstr = page_barstr + "<li><a href=\"javascript:void(0)\" id=\"pager_"+next_one+"\"> ></a></li>";
page_barstr = page_barstr + "<li><a href=\"javascript:void(0)\" id=\"pager_"+pages+"\">最後へ</a></li>";
}
}
return(page_barstr);
}
$(document).on("click", "[id^=pager_]", function () {
var id_str = $(this).attr("id");
stArray = id_str.split("_");
xxxxSearch(parseInt(stArray[1]));
});
});
<form>
<input type="text" name="searchkey" id="searchkey">
<button type="button" id="search_btn">検索</button>
</form>
<ul id="content_data">
</ul>
<ul id="pager" class="pagination"></ul>
さいごに
まぁ。カテゴリで検索とキーワードで検索わけちゃえばできそうだけど・・・
複合は、データ件数多いと厳しそう・・・
ただ、APIには記述はないが・・下記にcontent_fieldを指定すると絞り込みできるよってあるけど・・試してない・・
この辺り、API仕様書に反映してくれていれば・・時間節約できたかな。。。
https://www.movabletype.jp/documentation/mt8/designers-guide/search/contenttype/contenttype-search-page/
content_fieldは、コンテンツフィールドの名前もしくはユニーク ID と、コンテンツフィールドの値を、コロン(:)で分けて指定します。
content_field=コンテンツフィールドの名前:コンテンツフィールドの値こんな感じ・・だったと思う
関連
Movabletypeコンテンツデータ
https://www.omakase.net/blog/2022/11/movabletypecontent.html