製作者に知っていて欲しいWordPressのカスタムフィールドと検索の話

October 09, 2012

結論

カスタムフィールド系のプラグインを利用してカスタムフィールドの値をシリアライズ化して保存するプラグインは検索性を下げるので注意!絞込み検索を実装する時に苦労します。 そんな事知ってるし、何を今更ということでしたらそっとこのページを閉じて下さい。すみませんでした。

最初に

この件はカスタムフィールドの検索プラグインを作り始めて気づきました。 作っている途中のプラグインの話はまた別の機会として、カスタムフィールドを利用してサイトを構築してる人は多いと思いますがそのほとんどの方が何らかのカスタムフィールドプラグインを利用しているのではないかと思います。 そんな方々が対象のお話です。 正直言うと僕はカスタムフィールドを積極的に扱う案件には関わった事もなかったし、DB の構造にも興味がなかったのでシリアライズして値を保存していることなんて知りませんでした。 また、カスタムフィールド系のプラグインが素敵すぎて内部の動作のことは知らない、興味ない人も多いのではないかと思います。 さらに、以下に上げる相性の悪いプラグインが便利なプラグインとして多くのブログに紹介されているのを見て、導入してみたは良いものの後で困ったという事が減らせればと思いブログを書きました。 誤解がないように書きたいと思いますが、以下で紹介する相性の悪いプラグインは検索と相性が悪いだけで使い勝手が良い人気プラグインですのでそこのところをよろしくお願いします。

検索との相性の良いプラグインの条件

ひとつのカスタムフィールドのキーに対して複数の値がある場合、シリアライズ化せずに複数行(Row)に保存していること。これだけ シリアライズ化とは ≫ PHP: serialize - Manual こちらでシリアライズのテストできます

検索と相性のよいカスタムフィールドプラグインと相性の悪いプラグイン

相性が良い(シリアライズ化せずに複数行に保存している)

Custom Field Template Types - Complete Solution for Custom Fields and Types

相性が悪い(カスタムフィールドの値がシリアライズ化されている)

Advanced Custom Fields Magic Fields 2 ※他にも確認できていないプラグインがあるので、情報をお寄せ頂ければまとめたいと思います。また標準のカスタムフィールドを利用している方にはこの問題は発生しないと思います。

シリアライズ化されているとどんなことが起きるのか

以下は実験した DB の状態とその動作サンプル

実際にテストしてみた

meta_queryには以下の様なオプションがあります。

compare (string) - Operator to test. Possible values are ’=’, ‘!=’, ’>’, ’>=’, ’<’, ’<=’, ‘LIKE’, ‘NOT LIKE’, ‘IN’, ‘NOT IN’, ‘BETWEEN’, ‘NOT BETWEEN’. Default value is ’=‘.

compare オプションが ’=’ (完全一致の場合)

$args = array(
    'meta_query' => array(
        array(
            'key' => 'Favorite Fruits',
            'value' => 'orange',
            'compare' => '='
        )
    )
);

// クエリ
$the_query = new WP_Query($args);

期待通り post_id が 18 の投稿が表示される。

$args = array(
    'meta_query' => array(
        array(
            'key' => 'magic_fields',
            'value' => 'blue',
            'compare' => '='
        )
    )
);

// クエリ
$the_query = new WP_Query($args);

青枠の post*id が 24 の投稿を表示することを期待するけど、値がシリアライズ化され*a:2:{i:0;s:4:“blue”;i:1;s:11:“yellowgreen”;}となっているためblue_と一致せず

compare オプションが ‘LIKE’ (部分一致の場合)

$args = array(
    'meta_query' => array(
        array(
            'key' => 'magic_fields',
            'value' => 'blue',
            'compare' => 'LIKE'
        )
    )
);

// クエリ
$the_query = new WP_Query($args);

青枠の post_id が 24 の表示されるので良いようにもおもえますが、以下の様なクエリでも表示してしまう

$args = array(
    'meta_query' => array(
        array(
            'key' => 'magic_fields',
            'value' => 'green',
            'compare' => 'LIKE'
        )
    )
);

// クエリ
$the_query = new WP_Query($args);

本来はyellowgreenを検索した時に表示したいが、greenが部分一致してしまうために意図しない投稿を表示してしまう。 このようにシリアライズ化された値は検索性を著しく低下させるので、よろしくありません。 シリアライズ化して得られるメリットはデータベースの行数を抑えられること位でしょうか。

最後に

個人的にブログを運営しているだけならまだしも、サイト制作を請け負った場合で後からカスタムフィールドで検索したいとかいう要望がでた場合でその値がシリアライズ化されていたら僕なら\(^o^)/オワタとなります。(力技でなんとかなりますが、失敗したな〜とはなると思います。) ですので皆様、カスタムフィールド系のプラグインを導入する際はくれぐれもご注意下さい。 余談ですが、serialize にはこんなコメントがついてました。

参考リンク

Wordpress Hackers - Problem: WP_Query() with custom field value as an array … Data portability and data serialization in WordPress | WP Garage


Profile picture

Webのフロントエンドからバックエンド、プロトタイピングからプロダクションまで。定額の開発サービスも。詳しくはAboutページで。