Elasticsearchのような検索機能を提供するためのWordPressのプラグインを開発しました

WordPress

WordPressはデフォルトでキーワード検索機能がありますが、精度はあまりよくありません。

具体的には、例えば「php wordpress 管理サイト」のように検索した場合、これらすべての単語を含んでいる記事しか引っかかりません。

「wordpress」や「管理画面」が含まれる記事に検索者が知りたい情報があった可能性もありますが、検索者はあきらめて別のサイトに移動してしまうかもしれません。

Elasticsearchと呼ばれる全文検索エンジンの場合、検索ワードをすべて含んでいなくても検索結果に表示させることができます。

3分で分かった気になる、Elasticsearchとは? - Qiita
ログ解析等でよくElasticsearch+kibanaが使われているが、改めてElasticsearchとは?を簡単にまとめた。 ## 概要 - Elastic社が開発している、スケーラビリティに優れた全文検索エンジン - リア...
はじめての Elasticsearch - Qiita
この記事は全文検索エンジン「(」の入門チュートリアルです。 ## Elasticsearch とは **...

検索ワードを含むかではなく、検索ワードにどれくらいマッチしているかを評価し、評価の高い順に結果を返してくれるためです。

Elasticsearchは検索を劇的に改善してくれますが、使用するにはサーバにインストールしたりElastic Cloudのようなクラウドサービスを利用する必要があります。

今回作成したプラグインはそのElasticsearchのような全文検索を可能にするものです。

通常のプラグインと同様に導入することができ、別途必要なものはありません。

technote-space/wp-related-post-jp
WordPress recommendation plugin for Japanese. Contribute to technote-space/wp-related-post-jp development by creating an account on GitHub.

動作要件

PHP5.6以上が必要です。

導入手順

  1. githubからZIPをダウンロード ダウンロード
  2. wp-content/plugins に展開
  3. 管理画面から有効化
  4. 左メニュー「Related Post」 > 「進捗」から「インデックス処理を有効化」を押下

以上の手順で有効化しますが、処理が終わるまではキーワード検索に使用されません。

進捗状況は上記画面から確認できます。

完了するとインデックスされた結果が使用されるようになります。

特徴

ElasticsearchのようなAnalyzer

日本語の分かち書きにも対応しています。

Okapi BM25 アルゴリズムによる文章類似度計算

Okapi BM25 - Wikipedia
【技術解説】単語の重要度を測る?TF-IDFとOkapi BM25の計算方法とは - ミエルカAI は、自然言語処理技術を中心とした、RPA開発・サイト改善・流入改善レコメンドエンジンを開発
執筆:金子冴校閲:内野良一 世の中には単なるメモ書きから予算案,スポーツ記事や文学作品等,数えられないほどの文書が存在する.例えば,その数多の文書から「スポーツに関する記事が読みたい」と思った時,どれがスポーツに関する文書なのか判断する必要があるだろう.しかし,すべての文書を目で読んで判断することは到底不可能であり,現...

主な設定

  • バイグラムトークナイザーを使用するかどうか
    • true:
      文字列を2文字ずつ取り出して文章を構成する単語として使用します。
    • false:
      • ヤフーの設定をしている場合:
        ヤフーの日本語形態素解析サービスを使用して単語を分割します。
        利用制限があるため検索で使用する場合に制限に引っかかる可能性があります。
      • ヤフーの設定をしていない場合:
        Igoという形態素解析器を使用します。
        ローカルで動作させるため利用制限等はありませんが処理速度等はサーバに依存します。

関連記事を表示

インデックスされた情報は関連記事の表示に利用することが可能です。

関連記事を取得するクエリ生成前に以下のアクションを発行します。

do_action( 'related_post/on_related_post' );

このアクションが発行された後の一回のみ、WP_Queryはこのプラグインで算出された関連記事を返します。

例えば関連記事用のテンプレートを以下のように呼び出しているテーマの場合、

get_template_part('related-list');

functions.php 等に記述するコードは以下のようになります。

add_action( 'get_template_part_related-list', function () {
	do_action( 'related_post/on_related_post' );
} );

このプラグインの functions.php にはあらかじめ Cocoon 及び Simplicity2 用のコードが記述されているため、 それらのテーマを使用している方は別途設定は必要ありません。

インデックス対象を変更

デフォルトでは記事のタイトルと本文がインデックスの対象になっており、タイトルに重みづけがされています。

str_repeat( $post->post_title . ' ', 3 ) . $post->post_content;

「本文のみ」「タイトルのみ」「タイトルと本文とタグ」を対象とする設定があらかじめ別途用意されています。

以下のようなプログラムを functions.php などに記述することでそれらに変更することが可能です。

add_filter( 'related_post/extractor', function () {
	return 'content';            // 本文のみ
//	return 'title';              // タイトルのみ
//	return 'title_content_tags'; // タイトルと本文とタグ
} );

さらに以下のようなプログラムを記述することで、カスタムフィールドなどを含め自由に対象を設定することが可能です。

add_filter( 'related_post/extractor', function () {
	return false;
} );
add_filter( 'related_post/extractor_result', function ($d, $post) {
	return $post->title . ' ' . get_post_meta($post->ID, 'custom_field_key', true);
} );

関連記事の表示を変更

related_post/related_posts_content をフィルタすることで関連記事の表示を変更することが可能です。

変更例

add_filter( 'related_post/related_posts_content', function (
	/** @noinspection PhpUnusedParameterInspection */
	$content, $control, $title, $post, $related_posts
) {
	/** @var \Related_Post\Classes\Models\Control $control */
	/** @var string $title */
	/** @var array $related_posts */
	ob_start();
	?>
    <style>
        .related_posts_content {
            margin: 10px;
            padding: 10px;
            border: #ccc 1px solid;
            -webkit-transition: all 0.5s ease;
            -moz-transition: all 0.5s ease;
            -ms-transition: all 0.5s ease;
            -o-transition: all 0.5s ease;
            transition: all 0.5s ease;
            background: white;
        }

        .related_posts_content:hover {
            -webkit-box-shadow: #ccc 0 0 16px;
            -moz-box-shadow: #ccc 0 0 16px;
            box-shadow: #ccc 0 0 16px;
            background: #f0ffff;
        }

        .link-item {
            letter-spacing: -1em;
        }

        .link-item .thumbnail {
            display: inline-block;
            width: 20%;
            margin: 0;
            vertical-align: middle;
        }

        .link-item .thumbnail img {
            vertical-align: middle;
        }

        .link-item .title {
            display: inline-block;
            -webkit-box-sizing: border-box;
            -moz-box-sizing: border-box;
            box-sizing: border-box;
            width: 80%;
            padding: 1em;
            margin: 0;
            font-weight: bold;
            letter-spacing: normal;
        }
    </style>
    <div class="related_posts">
        <h3 class="related_posts_title">
			<?php $control->h( $title ); ?>
        </h3>
        <div class="related_posts_wrap">
			<?php foreach ( $related_posts as $related_post ): ?>
				<?php /** @var WP_Post $related_post */ ?>
                <div class="related_posts_content">
					<?php $control->url( get_permalink( $related_post->ID ), <<< EOS
                    <div class="link-item">
                        <div class="thumbnail">
                            {$control->get_thumbnail( $related_post->ID )}
                        </div>
                        <div class="title">
                            {$related_post->post_title}
                        </div>
                    </div>
EOS
						, false, false, [], true, false ); ?>
                </div>
			<?php endforeach; ?>
        </div>
    </div>
	<?php

	$view = ob_get_contents();
	ob_end_clean();

	return $view;
}, 10, 5 );

以下のようなサムネイル付きの表示に変更されます。

要望・バグ報告等

technote-space/wp-related-post-jp
WordPress recommendation plugin for Japanese. Contribute to technote-space/wp-related-post-jp development by creating an account on GitHub.

まとめ

検索はサイト内の別の記事を見てもらえるチャンスであり、検索結果に何もでなくなってしまうのは大きな損失になってしまいます。

分散処理もできるElasticsearchの導入がおススメですが、それが困難な場合の代わりにはぜひプラグインを導入してみてください。

コメント

タイトルとURLをコピーしました