ちょっと話題の記事

WordPressの検索機能にElasticsearchを利用する

2016.05.31

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

こんにちは、藤本です。

先日、AMIMOTO + Amazon Elasticsearch ServiceでWordPressの検索機能をパワーアップするという記事を見つけました。Wordpressの検索機能をデータベースではなく、Elasticsearchに委譲するPluguinです。大変興味があったので、早速、試してみました。

Amazon Elasticsearch Serviceドメイン作成

ElasticsearchにはAmazon ESを利用します。Amazon Elasticsearch Serviceのドメイン作成は[新機能]Amazon Elasticsearch Serviceがリリースされました!を参照。

WordPressのインストール

WordPressのインストールはこちらを参考にインストールしてください。

# yum install -y httpd24 php56 php56-mysqlnd php56-mbstring mysql-server
# /etc/init.d/mysqld start
# mysql
mysql> create database wordpress;
mysql> grant all on wordpress.* to wpuser@localhost identified by 'password';
mysql> flush PRIVILEGES;

# wget https://ja.wordpress.org/latest-ja.tar.gz
# tar xzf latest-ja.tar.gz -C /var/www
# sed -ie 's/^DocumentRoot.*/DocumentRoot "\/var\/www\/wordpress"/g' /etc/httpd/conf/httpd.conf
# /etc/init.d/httpd start

Pluginインストール

AMIMOTO + Amazon Elasticsearch ServiceでWordPressの検索機能をパワーアップするでご紹介されているPluginをインストールします。

# yum install git -y
# cd /var/www/wordpress/wp-content/plugins
# git clone https://github.com/horike37/wp-elasticsearch.git
# cd wp-elasticsearch
# git checkout remotes/origin/scrutinizer-patch-1

# yum install nodejs npm --enablerepo=epel -y
# php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
# php composer-setup.php
# php -r "unlink('composer-setup.php');"

# cd /var/www/wordpress/wp-content/plugins/wp-elasticsearch
# npm install
# ~/composer.phar update
# ~/composer.phar install
# ~/composer.phar require aws/aws-sdk-php egeloen/http-adapter guzzlehttp/guzzle monolog/monolog
# chown -R apache:apache /var/www/wordpress

GUIからの設定

Pluginの有効化

WordPressのPlugin設定画面でWP Elasticsearchを有効化します。

wordpress-plugin

WP Elasticsearch設定

WP Elasticsearchの設定画面からElasticsearchの設定を行います。

  • Elasticsearch Endpoint : Elasticsearchのエンドポイント
  • Port : Elasticsearchへアクセスするポート番号。Amazon ESの場合、80、もしくは443
  • index : Elasticsearchのインデックス名
  • type : 上記インデックスのタイプ名
  • Costom Fields : Elasticsearchへ渡すフィールド(デフォルトの場合、タイトル、本文の2つ)

WP_Elasticsearch_‹_テストサイト_—_WordPress

Elasticsearchにブログ記事を同期する

同設定画面で同期を実行し、Elasticsearchへデータを同期します。

WP_Elasticsearch_‹_テストサイト_—_WordPress 4

同期データの確認

KibanaからIndexを確認します。

kibana-settings

WordPressという名前でインデックスが作成されているのがわかります。

同期されたデータを確認します。

Discover_-_Kibana_4

ブログのタイトル、記事本文が登録されています。

検索

WordPressの画面から検索を行います。バックエンドの検索がElasticsearchに変わっているだけなので利用者視点では見た目上は変化が分かりません。

テストサイト_–_Just_another_WordPress_site

今回は分かりやすく、like検索だと引っかからないようなキーワードを指定します。

検索結果_–_テストサイト

通常のlike検索では引っかからないはずなので、Elasticsearchによる検索ができているようです。

むむっ、検索キーワードが消える。。

IAM認証対応

AMIMOTO + Amazon Elasticsearch ServiceでWordPressの検索機能をパワーアップするの中でAmazone Elasticsearch ServiceのIAM認証に対応できていないという記載があったので、実装方法を調べてみました。

wp-elasticsearchではElasticsearchのSDKにruflin/Elasticaを利用しています。Issuesで検索したら、IAM対応が3月にマージされていました。

phpは読んだことも、書いたこともないですが、ソースコードを見てみると分かりやすい実装だったので習って以下のように修正して、IAM認証に対応できるようにしました。

wp-elasticsearch.php
diff --git a/wp-elasticsearch.php b/wp-elasticsearch.php
index 448c0be..7205915 100644
--- a/wp-elasticsearch.php
+++ b/wp-elasticsearch.php
@@ -197,10 +197,28 @@ class WP_Elasticsearch {
                        return false;
                }

-               $client = new \Elastica\Client( array(
+               $es_options = array(
                        'host' => $options['endpoint'],
                        'port' => $options['port'],
-               ));
+               );
+               if ( isset($options['aws_auth']) ) {
+                       $es_options['persistent'] = false;
+                       $es_options['transport'] = 'AwsAuthV4';
+
+                       if ( !empty( $options['access_key'] ) && !empty( $options['secret_key'] ) ) {
+                               $es_options['aws_access_key_id'] = $options['access_key'];
+                               $es_options['aws_secret_access_key'] = $options['secret_key'];
+                       }
+                       if ( !empty( $options['region'] ) ) {
+                               $es_options['aws_region'] = $options['region'];
+                       }
+               }
+                $client = new \Elastica\Client( $es_options );
                return $client;
        }
}
admin/option.php
diff --git a/admin/option.php b/admin/option.php
index ece097e..d02d2a5 100644
--- a/admin/option.php
+++ b/admin/option.php
@@ -38,6 +38,38 @@ function wpels_settings_init() {
        );

        add_settings_field(
+               'aws_auth',
+               __( 'AWS Auth', 'wp-elasticsearch' ),
+               'aws_auth_render',
+               'wpElasticsearch',
+               'wpels_wpElasticsearch_section'
+       );
+
+       add_settings_field(
+               'access_key',
+               __( 'AWS Access Key', 'wp-elasticsearch' ),
+               'access_key_render',
+               'wpElasticsearch',
+               'wpels_wpElasticsearch_section'
+       );
+
+       add_settings_field(
+               'secret_key',
+               __( 'AWS Secret Key', 'wp-elasticsearch' ),
+               'secret_key_render',
+               'wpElasticsearch',
+               'wpels_wpElasticsearch_section'
+       );
+
+       add_settings_field(
+               'region',
+               __( 'Region', 'wp-elasticsearch' ),
+               'region_render',
+               'wpElasticsearch',
+               'wpels_wpElasticsearch_section'
+       );
+
+       add_settings_field(
                'index',
                __( 'index', 'wp-elasticsearch' ),
                'index_render',
@@ -84,6 +116,46 @@ function port_render() {
 }


+function aws_auth_render() {
+
+       $options = get_option( 'wpels_settings' );
+       ?>
+       <input type='checkbox' name='wpels_settings[aws_auth]' value='true' <?php if(!empty($options['aws_auth'])) { echo 'checked'; } ?>>
+       <?php
+
+}
+
+
+function access_key_render() {
+
+       $options = get_option( 'wpels_settings' );
+       ?>
+       <input type='text' name='wpels_settings[access_key]' value='<?php echo $options['access_key']; ?>'>
+       <?php
+
+}
+
+
+function secret_key_render() {
+
+       $options = get_option( 'wpels_settings' );
+       ?>
+       <input type='text' name='wpels_settings[secret_key]' value='<?php echo $options['secret_key']; ?>'>
+       <?php
+
+}
+
+
+function region_render() {
+
+       $options = get_option( 'wpels_settings' );
+       ?>
+       <input type='text' name='wpels_settings[region]' value='<?php echo $options['region']; ?>'>
+       <?php
+
+}
+
+
 function index_render() {

        $options = get_option( 'wpels_settings' );

対応内容

  • IAM Userのアクセスキーによる認証
  • EC2に設定されたIAM Roleによる認証

設定画面は以下のように項目が増えています。

WP_Elasticsearch_‹_さいと_—_WordPress

IAM認証を利用する場合はAWS Authにチェックを付けます。

その上でIAM Userのアクセスキーで認証したい場合、Access Key、Secret Key、Region(Amazon ESのリージョン名)を指定してください。Amazon ESへのアクセス権限を持つIAM Roleを設定したEC2で利用する場合、Region(Amazon ESのリージョン名)のみを指定してください。

まとめ

いかがでしたでしょうか?
Wordpressは長く運用しているとデータベースが肥大化し、検索機能がボトルネックとなってしまいます。そこで検索機能を外部に委譲することでデータベースの負荷を軽減し、より高速な検索結果をエンドユーザーに返すことができます。更に今回のようにElasticsearchにAWSフルマネージドサービスであるAmazon Elasticsearch Serviceを利用することで運用負荷は大きくならないのは嬉しいことですね。

参考資料