2015.12.09追記
もっといい方法がありましたので別記事にまとめました。
meta_queryは文字列の一致だけでなく、「compare」に等号・不等号や「BETWEEN」という語句を与えることで数値としての条件を設定することができます。
価格範囲による検索や広さなどで扱えそうですね。
便利な機能ですが、小数を含む数値を扱った際に正常に動作しないということがありました。
原因と対策を紹介します。
ADs
たとえば、「parameter」というカスタムフィールドの値が「2.8以上5.6以下」の記事を抽出する場合を考えてみます。
ドキュメント通りなら以下のようになりますが、これでは意図した記事が抽出されません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
function customize_main_query($query) { if ( is_admin() || ! $query->is_main_query() ) return; if ( $query->is_search() ) { $query->set( 'meta_query', array( array( 'key' => 'parameter', 'value' => array(2.8,5.6), 'compare' => 'BETWEEN', 'type' => 'DECIMAL' ) ) ); } } add_action( 'pre_get_posts', 'customize_main_query' ); |
上記のアクションフックを適用したとき、記事抽出のためにどのようなSQL文が発行されるかを確認してみると以下のようになります。
1 2 3 4 5 6 7 8 9 10 |
( wp_postmeta.meta_key = 'parameter' AND CAST(wp_postmeta.meta_value AS DECIMAL) BETWEEN '2.8' AND '5.6' ) /* 以下のコードでJOIN/WHERE句を確認できます function meta_query_decimal( $array ) { var_dump($array); return $array; } add_filter('get_meta_sql','meta_query_decimal'); */ |
CAST(wp_postmeta.meta_value AS DECIMAL)という部分が問題なのですが、「DECIMAL」に属性がセットされていないため、小数点以下を四捨五入してしまいます。
MySQLがインストールされている環境なら以下のようにテストしてみると分かりやすいかと思います。
1 2 3 4 5 |
mysql > SELECT CAST(2.8 AS DECIMAL) -> 6 mysql > SELECT CAST(5.4 AS DECIMAL) -> 5 |
DECIMALは属性なしの場合、合計10桁で小数点以下はなしの数値に丸められます。
数値型(データ型)のまとめ – [MySQL/SQL] ぺんたん info
アンパック浮動小数点数。CHAR カラムのように動作する。
アンパック” とは、その数値が、各桁に 1 文字ずつ使用して文字列として格納されることを意味する。M では、小数点と、負数に使用される ‘-‘ 記号はカウントされない(しかし、これらのためのスペースは確保される)。D が 0 の場合、値は小数点も小数部も持たない。DECIMAL 値の最大範囲は、DOUBLE と同じだが、個々の DECIMAL カラムの実際の範囲は、M と D の値によって制限される。UNSIGNED を指定した場合、負数は使用できない。
D を省略した場合、デフォルトは 0。M を省略した場合、デフォルトは 10
MySQL バージョン 3.23 より前のバージョンでは、M 引数に、符号と小数点に必要なスペースを含める必要がある
上記のpre_get_postsアクションフックに加え、発行されるSQL文に対するフィルターフックを使ってDECIMAL部分に属性を追加します。
1 2 3 4 5 6 7 8 |
//合計10桁以内、小数点第2位までを扱えるようにする //扱う数値によっては(10,3)ではないかもしれないので注意 function cast_decimal_precision( $array ) { $array['where'] = str_replace('DECIMAL','DECIMAL(10,3)',$array['where']); return $array; } add_filter('get_meta_sql','cast_decimal_precision'); |
この手法は先日作成した2.5ジゲンフォトで、焦点距離や絞りなどの数値検索を実装するために利用しました。
絞り値には小数が含まれるため、検索結果が意図した結果にならずに困っていました。
販売価格をドルで表記するショッピングサイトや平米数を記載する不動産サイトなど、小数を扱うおそれのあるサイトでは気をつけたほうがいいかもしれません。
ADs
コメントはまだありません。