SearchEstraierプラグインは、Hyper Estraierを利用したサイト内全文検索 (サイト内検索) 機能を提供します。 従来のSQLを使った複数条件指定検索に加え、数万ページでも高速に動作する全文検索機能を利用できるようになります。キーワードにマッチするコンテンツをスコア順に抽出できます。
このWebサイトのドキュメント検索機能は、このプラグインを利用して実装されています。
MeCabがインストールされている時、文書内のキーワードを自動抽出して、レコメンドAPIによる「閲覧履歴による興味関心」の精度を上げることができます。
あわせて php-mecabのインストールを推奨します(必須ではありません)。
以下の環境変数を config.json の config_settings に記述します。
環境変数「searchestraier_skip_noindex」を true にすると、「<meta name=robots content=noindex>
」に相当するタグが含まれる HTML 文書を検索インデックスに含めないようにします。
以下のようなビューを作成します。
なお、以下サンプルでは後述のページネーション用のインクルード・モジュール「SearchEstraierPagination」を別途用意してインクルードを行っています。
<form method="GET" action="<mt:var name="current_archive_url">">
<div class="form-inline">
<label> キーワード
<input type="text" name="query" value="<mt:var name="query" escape>"></label>
<label>
<input type="radio" name="and_or" value="AND" <mt:if name="request.and_or" eq="AND">checked</mt:if>>
AND
</label>
<label>
<input type="radio" name="and_or" value="OR" <mt:if name="request.and_or" eq="OR">checked</mt:if>>
AND
</label>
<button type="submit">検索</button>
</div>
</form>
<mt:var name="request.query" setvar="query">
<mt:estraiersearch phrase="$query" prefix="estraier_" and_or="AND" default_limit="10" snippet_width="200" workspace_ids="0,1">
<mt:if name="__first__">
<p>
「<mt:var name="query" escape>」の検索結果( <mt:var name="estraier_hit">件ヒットしました )
</p>
<ul class="list-unstyled"></mt:if>
<mt:if name="estraier_thumbnail_square">
<mt:var name="estraier_thumbnail_square" setvar="thumbnail_url">
<mt:else>
<mt:setvarblock name="thumbnail_url"><mt:var name="theme_static">website/images/no-image.png</mt:setvarblock>
</mt:if>
<li class="mb-2"><div class="d-flex"><div class="thumbnail"><img src="<mt:var name="thumbnail_url" escape>" width="80" height="80" alt=""></div>
<div><a href="<mt:var name="estraier_uri" escape>"><strong><mt:var name="estraier_title" escape></strong></a>
<p class="snippet"><mt:var name="estraier_snippet"></p></div></div>
</li>
<mt:if name="__last__">
</ul>
<mt:setvar name="estraier_hit" value="search_hit">
<mt:include module="SearchEstraierPagination">
</mt:if>
</mt:estraiersearch>
<mt:if name="query">
<mt:unless name="search_hit">
<p>「<mt:var name="query" escape>」にマッチするページはありませんでした。</p>
</mt:unless>
</mt:if>
それぞれのサンプルテンプレートを下記に記載します。
ページネーション用のテンプレートは <mt:estraiersearch>
タグ内でのみ利用可能な変数 ( estraier_*
) を用いて作成します。
<mt:if name="estraier_pagertotal" gt="1">
<mt:setvarblock name="pagnation_base_url"><mt:var name="current_archive_url">?query=<mt:var name="query" escape encode_url="1"><mt:if name="request.and_or">&and_or=<mt:var name="request.and_or" escape></mt:if></mt:setvarblock>
<mt:for from="1" to="$estraier_pagertotal">
<mt:if name="__first__">
<nav aria-label="ページネーション">
<ul>
<li><a aria-label="先頭へ" href="<mt:var name="pagnation_base_url">">«</a></li>
<mt:if name="request.offset">
<li><a aria-label="前へ" href="<mt:var name="pagnation_base_url">&offset=<mt:var name="estraier_prevoffset">">‹</a></li>
</mt:if>
</mt:if>
<mt:var name="search_offset" value="$__index__">
<mt:var name="search_offset" op="*" value="$estraier_limit">
<li class="<mt:if name="__value__" eq="$estraier_currentpage">active</mt:if>">
<a href="<mt:var name="pagnation_base_url">&offset=<mt:var name="search_offset">"><mt:var name="__value__"></a>
</li>
<mt:if name="__last__">
<mt:if name="estraier_nextoffset">
<li><a aria-label="次へ" href="<mt:var name="pagnation_base_url">&offset=<mt:var name="estraier_nextoffset">">›</a></li>
</mt:if>
<mt:var name="search_offset" value="$estraier_pagertotal">
<mt:var name="search_offset" op="-" value="1">
<mt:var name="search_offset" op="*" value="$estraier_limit">
<li><a aria-label="最後へ" href="<mt:var name="pagnation_base_url">&offset=<mt:var name="search_offset">">»</a></li>
</ul>
</nav>
</mt:if>
</mt:for>
</mt:if>
モジュール内で setvar
しているテンプレート・変数「pagnation_item_width
」の数値で、表示中のページの前後に表示するリンクの数を設定します。
<mt:if name="estraier_pagertotal" gt="1">
<mt:ignore>Pagenation Settings</mt:ignore>
<mt:setvar name="pagnation_item_width" value="4">
<mt:math eq="x * 2 + 1" x="$pagnation_item_width" setvar="pagnation_item_limit">
<mt:setvar name="pagnation_item_start" value="1">
<mt:setvar name="pagnation_item_end" value="$estraier_pagertotal">
<mt:if name="estraier_pagertotal" gt="$pagnation_item_limit">
<mt:math eq="x + y" x="$estraier_currentpage" y="$pagnation_item_width" setvar="pagnation_item_end">
<mt:if name="pagnation_item_end" gt="$estraier_pagertotal"><mt:setvar name="pagnation_item_end" value="$estraier_pagertotal"></mt:if>
<mt:if name="pagnation_item_end" lt="$pagnation_item_limit"><mt:setvar name="pagnation_item_end" value="$pagnation_item_limit"></mt:if>
<mt:math eq="x - y" x="$estraier_currentpage" y="$pagnation_item_width" setvar="pagnation_item_start">
<mt:math eq="1 + x - y" x="$pagnation_item_end" y="$pagnation_item_start" setvar="pagnation_item_total">
<mt:if name="pagnation_item_total" lt="$pagnation_item_limit">
<mt:math eq="x + y - z" x="$pagnation_item_start" y="$pagnation_item_total" z="$pagnation_item_limit" setvar="pagnation_item_start">
</mt:if>
<mt:if name="pagnation_item_start" le="0"><mt:setvar name="pagnation_item_start" value="1"></mt:if>
</mt:if>
<mt:setvarblock name="pagnation_base_url"><mt:var name="current_archive_url">?query=<mt:var name="query" escape encode_url="1"><mt:if name="request.and_or">&and_or=<mt:var name="request.and_or" escape></mt:if></mt:setvarblock>
<mt:for from="$pagnation_item_start" to="$pagnation_item_end">
<mt:if name="__first__">
<nav aria-label="ページネーション">
<ul>
<li><a aria-label="先頭へ" href="<mt:var name="pagnation_base_url">">«</a></li>
<mt:if name="request.offset">
<li><a aria-label="前へ" href="<mt:var name="pagnation_base_url">&offset=<mt:var name="estraier_prevoffset">">‹</a></li>
</mt:if>
<mt:if name="pagnation_item_start" gt="1">
<li><span>...</span></li>
</mt:if>
</mt:if>
<mt:math eq="x * ( y - 1 )" x="$estraier_limit" y="$__value__" setvar="pagnation_offset">
<li class="<mt:if name="__value__" eq="$estraier_currentpage">active</mt:if>">
<a href="<mt:var name="pagnation_base_url">&offset=<mt:var name="pagnation_offset">"><mt:var name="__value__"></a>
</li>
<mt:if name="__last__">
<mt:if name="pagnation_item_end" lt="$estraier_pagertotal">
<li><span>...</span></li>
</mt:if>
<mt:if name="estraier_nextoffset">
<li><a aria-label="次へ" href="<mt:var name="pagnation_base_url">&offset=<mt:var name="estraier_nextoffset">">›</a></li>
</mt:if>
<mt:math eq="x * ( y - 1 )" x="$estraier_limit" y="$estraier_pagertotal" setvar="pagnation_offset">
<li><a aria-label="最後へ" href="<mt:var name="pagnation_base_url">&offset=<mt:var name="pagnation_offset">">»</a></li>
</ul>
</nav>
</mt:if>
</mt:for>
</mt:if>
検索インデックスに登録された属性を利用して検索を絞り込むことができます。
<mt:estraiersearch> ~ </mt:estraiersearch>
タグに属性を指定します。
ad_attr(s)
: 属性検索対象の属性(単一もしくは配列)add_condition(s)
: 属性検索条件 (単一もしくは配列、詳細は https://dbmx.net//hyperestraier/uguide-ja.html を参照)values(s)
: 属性検索の値(単一もしくは配列)検索インデックスに登録されている属性は、SearchEstraier プラグイン設定から確認できます。
プラグイン「SearchEstraier」にプラグイン設定画面から検索インデックスの状態を確認する機能を追加しました。
<mt:ignore>
- タイトル ( @title 属性 ) に 'ドキュメント' を含む
</mt:ignore>
<mt:var name="request.query" setvar="query">
<mt:estraiersearch phrase="$query" prefix="estraier_" and_or="AND" default_limit="10" snippet_width="200" ad_attr="@title" add_condition="STRINC" value="ドキュメント">
<!-- do something -->
</mt:estraiersearch>
<mt:ignore>
- モデル ( @model 属性 ) が 'entry' と等しい
- ページの URL ( @uri 属性 ) が 'https://example.com/blog/' に前方一致する
</mt:ignore>
<mt:block from_json="search_attrs">["@model", "@uri"]</mt:block>
<mt:block from_json="search_conditions">["STREQ", "STRBW"]</mt:block>
<mt:block from_json="search_values">["entry", "https://example.com/blog/"]</mt:block>
<mt:var name="request.query" setvar="query">
<mt:estraiersearch phrase="$query" prefix="estraier_" and_or="AND" default_limit="10" snippet_width="200" ad_attrs="$search_attrs" add_conditions="$search_conditions" values="$search_values">
<!-- do something -->
</mt:estraiersearch>
<アプリのURL>/plugins/SearchEstraier/app/pt-recommend-api.php
必要に応じて別の場所に移動してください。
pt-recommend-api.php?url=<mt:var name="current_archive_url" escape="url">&workspace_ids=0,1&type=interest&limit=5&model=page
※ typeパラメタに渡せるのは、similar(類似)、interest(閲覧履歴による興味関心)、both(その両方)です。
{"interest":[{"snippet":"フォーム機能で作成した設問に対するカスタム・バリデーションをプラグインで作成することができます... ",
"uri":"https:\/\/powercmsx.jp\/about\/form_validation_plugin.html",
"author":"Junnama Noda",
"cdate":"2019-04-01T15:23:27Z",
"description":"PowerCMS Xは日本国内で導入実績 3,000 サイトを超える、高性能・高機能...",
"digest":"79eff0c3f31662ac08078d4dc028f52b",
"extracted":"バリデーション,フォーム,テキスト,フィールド",
"mdate":"2019-04-01T15:23:21Z",
"metadata":"設問の作成画面,生成された設問,CustomValidation.zip (4KB),About PowerCMS X,ドキュメント",
"mime_type":"text\/html",
"model":"page",
"object_id":"530",
"site_name":"PowerCMS X",
"tags":"ドキュメント",
"thumbnail":"https:\/\/powercmsx.jp\/assets\/thumbnails\/thumb-400xauto-174-file.png",
"thumbnail_square":"https:\/\/powercmsx.jp\/assets\/thumbnails\/thumb-400xauto-square-174-file.png",
"title":"フォームのバリデーション・プラグインの作成",
"workspace_id":"1"}],
"similar":[{"snippet":"静的に生成されたオブジェクトの一覧ページに特定のパラメタを付与することで、動的ページネーションを実装できます... ",
"uri":"https:\/\/powercmsx.jp\/about\/pagination.html",
"author":"Junnama Noda",
"cdate":"2019-01-07T11:00:00Z",
"description":"静的(スタティック)ページ作成をベースとしながら、サイト内検索やページネーション、ログインが必要な会員サイト、フォームへの投稿など...",
"digest":"eb0fab9d404cc063d093f1df6e092c7d",
"extracted":"ページネーション",
"mdate":"2019-01-07T11:15:08Z",
"metadata":"ページネーション(スクリーンショット),About PowerCMS X,ドキュメント",
"mime_type":"text\/html",
"model":"page",
"object_id":"400",
"site_name":"PowerCMS X",
"tags":"ドキュメント",
"thumbnail":"https:\/\/powercmsx.jp\/assets\/thumbnails\/thumb-400xauto-153-file.png",
"thumbnail_square":"https:\/\/powercmsx.jp\/assets\/thumbnails\/thumb-400xauto-square-153-file.png","title":"ページネーション",
"workspace_id":"1"}]}
<mt:ignore>Move style elements into the head element.</mt:ignore>
<style type="text/css">
.recommend-list li:first-child { border-top: 1px solid #ccc; }
.recommend-list_item { border-bottom: 1px solid #ccc; padding: 10px 10px 10px 0; }
.recommend-list_item img { border: 1px solid #ccc; }
.recommend-link{ display: block; overflow: hidden; text-overflow: ellipsis; }
.recommend-thumbnail{ min-width : 50px; margin-right: 10px; }
.recommend-date{ color: #777; font-size: 90%; }
</style>
<div class="container-fluid">
<div class="row">
<div class="col-lg-12">
<div id="similar-list-wrapper" style="display:none;">
<h2 class="font-weight-normal"><small>関連性の高いページ</small></h2>
<ul id="similar-list" class="list-unstyled ml-0 recommend-list">
</ul>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div id="interest-list-wrapper" style="display:none">
<h2 class="font-weight-normal"><small>あなたへのお勧め</small></h2>
<ul id="interest-list" class="list-unstyled ml-0 recommend-list">
</ul>
</div>
</div>
</div>
</div>
<script>
$(function(){
$.ajax({
url: '<mt:property name="path">plugins/SearchEstraier/app/pt-recommend-api.php?type=both&limit=4&url=<mt:var name="current_archive_url" escape="url">',
type: 'GET',
dataType: 'json',
timeout: 10000,
success: function( responce ){
similar = responce.similar;
append_recommend( similar, 'similar' );
interest = responce.interest;
append_recommend( interest, 'interest' );
},
error: function(){
// error
}
});
});
function append_recommend( recommend, target ){
if ( recommend.length > 0 ) {
for(let k in recommend) {
var uri = recommend[k].uri;
var title = recommend[k].title;
var thumbnail = recommend[k].thumbnail_square;
if (! thumbnail ) {
thumbnail = '<mt:var name="theme_static">website/images/no-image.png';
}
var cdate = recommend[k].cdate;
cdate = cdate.replace('T', ' ');
cdate = cdate.replace('Z', '');
cdate = cdate.replace( /:[0-9]{2}$/, '');
cdate = '<mt:trans phrase="Publish Date"> : ' + cdate;
var link = $('<a>', { text : title, href : uri, class : 'recommend-link' });
var flex_wrapper = $('<div>', { class : 'd-flex' } );
var litag = $('<li>', { class : 'recommend-list_item' });
var img = $('<img>', { src : thumbnail, alt: '', width: 50, height : 50 });
var thumb_wrapper = $('<div>', { class : 'recommend-thumbnail' } );
var link_wrapper = $('<div>', { class : 'recommend-link-wrapper' } );
var date_wrapper = $('<span>', { text : cdate, class : 'recommend-date' });
link_wrapper.append(link);
thumb_wrapper.append(img);
flex_wrapper.append(thumb_wrapper);
link_wrapper.append(date_wrapper);
flex_wrapper.append(link_wrapper);
litag.append(flex_wrapper);
$('#'+target+'-list').append(litag);
}
$('#'+target+'-list-wrapper').show();
}
}
</script>