べんりワザ・WordPressのテンプレートと投稿の取得

meta_queryでカスタムフィールドで絞る・並べ替える

価格・在庫・イベント日など、カスタムフィールドの値で投稿を絞りこむmeta_queryの書き方。compareとtypeの早見表、数値順に並べるmeta_value_num、うまく効かないときの原因をまとめました。

「3000円以下の商品だけ」「在庫があるものだけ」——カスタムフィールドの値で投稿を絞りこむのがmeta_queryです。基本の形はtax_queryと同じ二重構造です。

<?php
$query = new WP_Query([
  'post_type'  => 'shohin',
  'meta_query' => [
    [
      'key'     => 'price',      // フィールド名
      'value'   => 3000,         // 比べる値
      'compare' => '<=',         // 比べ方
      'type'    => 'NUMERIC',    // 値の型(数値なら必須)
    ],
  ],
]);
?>

最重要ポイントはtype。これを忘れると数値の大小がおかしくなります(理由は後述)。

4つのキーの意味

キー役割よく使う値
keyカスタムフィールドの名前'price' 'event_date'
value比べる値数値・文字列・配列
compare比べ方'='(既定)'!=' '>' '>=' '<' '<=' 'LIKE' 'IN' 'NOT IN' 'BETWEEN' 'EXISTS' 'NOT EXISTS'
type値の型'CHAR'(既定)'NUMERIC' 'DATE' 'DATETIME' 'DECIMAL'

なぜtypeが必要なのか

WordPressはカスタムフィールドの値を、種類を区別せず文字列として保存しています。そのためtypeを指定しないと、比較も文字列のルールで行われます。

  • 文字列として比べると——'100''99' より小さい(先頭の1と9を比べるため)
  • 'type' => 'NUMERIC'を付けると——数値として比べるので100 > 99

価格・在庫数・点数など数値を扱うときは、必ず'type' => 'NUMERIC'。小数を含むなら'DECIMAL'を使います。

compareの実例

// 在庫が1以上(在庫あり)
['key' => 'stock', 'value' => 0, 'compare' => '>', 'type' => 'NUMERIC'],

// 1000円〜3000円
['key' => 'price', 'value' => [1000, 3000], 'compare' => 'BETWEEN', 'type' => 'NUMERIC'],

// サイズがS・Mのどちらか
['key' => 'size', 'value' => ['S', 'M'], 'compare' => 'IN'],

// 部分一致(説明文に「限定」を含む)
['key' => 'note', 'value' => '限定', 'compare' => 'LIKE'],

// そのフィールドに何か入っている投稿だけ
['key' => 'price', 'compare' => 'EXISTS'],

// そのフィールドが空(または未設定)の投稿だけ
['key' => 'price', 'compare' => 'NOT EXISTS'],

BETWEENINvalueを配列で渡すのが決まりです。

複数の条件を組み合わせる

relationでつなぎ方を決めます(省略時はAND)。

'meta_query' => [
  'relation' => 'AND',
  ['key' => 'price', 'value' => 3000, 'compare' => '<=', 'type' => 'NUMERIC'],
  ['key' => 'stock', 'value' => 0,    'compare' => '>',  'type' => 'NUMERIC'],
],

入れ子にすれば「(AかB)かつC」も書けます。

'meta_query' => [
  'relation' => 'AND',
  [
    'relation' => 'OR',
    ['key' => 'is_new',  'value' => '1'],
    ['key' => 'is_sale', 'value' => '1'],
  ],
  ['key' => 'stock', 'value' => 0, 'compare' => '>', 'type' => 'NUMERIC'],
],

カスタムフィールドの値で並べ替える

絞りこみとは別に、並べ替えでもカスタムフィールドが使えます。meta_keyorderbyの組み合わせです。

// 価格の安い順
$query = new WP_Query([
  'post_type' => 'shohin',
  'meta_key'  => 'price',
  'orderby'   => 'meta_value_num',   // 数値として並べる
  'order'     => 'ASC',
]);
  • 'orderby' => 'meta_value_num'——数値として並べる(価格・点数・在庫)
  • 'orderby' => 'meta_value'——文字列として並べる(名前・カナ・Ymd形式の日付)

2つの基準で並べ替える(名前付きの条件)

meta_queryの条件に名前を付けると、orderbyからその条件を指定できます。「おすすめ順→価格の安い順」のような多段の並べ替えです。

$query = new WP_Query([
  'post_type'  => 'shohin',
  'meta_query' => [
    'featured' => ['key' => 'is_featured', 'compare' => 'EXISTS'],
    'price'    => ['key' => 'price',       'compare' => 'EXISTS', 'type' => 'NUMERIC'],
  ],
  'orderby' => [
    'featured' => 'DESC',
    'price'    => 'ASC',
  ],
]);

配列のキー(featured price)が条件の名札になり、orderbyでその順番を指定できます。

日付フィールドで絞る

ACF(SCF)の日付フィールドは、既定で20260725のようなYmdの文字列で保存されています。この形式なら文字列のままでも大小比較が正しく効くので、そのまま使えます。

// 今日以降のイベントだけ、開催日の近い順に
$query = new WP_Query([
  'post_type'  => 'event',
  'meta_key'   => 'event_date',
  'orderby'    => 'meta_value',
  'order'      => 'ASC',
  'meta_query' => [
    [
      'key'     => 'event_date',
      'value'   => date('Ymd'),
      'compare' => '>=',
    ],
  ],
]);

保存形式が2026-07-25のようにハイフン入りの場合は、'type' => 'DATE'を付けて比較します。

べんりワザACFフィールド別・表示の書き方早見表ACFの日付フィールドの保存形式と表示の整形はこちら

実例:絞りこみフォームと組み合わせる

URLのパラメータ(?max_price=3000)を受け取って条件を組み立てるパターンです。

<?php
$args = ['post_type' => 'shohin', 'posts_per_page' => 12];

if (!empty($_GET['max_price'])) {
  $args['meta_query'][] = [
    'key'     => 'price',
    'value'   => (int) $_GET['max_price'],   // 必ず数値に変換
    'compare' => '<=',
    'type'    => 'NUMERIC',
  ];
}

$query = new WP_Query($args);
?>

重くなってきたら設計を見直す

投稿メタは「1行に1つの値」という形で保存されているため、条件が増えるほどデータベースの結合が増えて遅くなります

  • 絞りこみの軸が決まっている(季節・ブランド・カテゴリ)→ カスタムタクソノミーにしてtax_queryのほうが速い
  • 絞りこみの軸が数値の範囲(価格・面積)→ meta_queryが向いている

「一覧で絞りこみに使う項目はタクソノミー、詳細ページで表示するだけの項目はカスタムフィールド」——この分け方が、あとから効いてくる設計判断です。

べんりワザtax_queryでカテゴリ・タクソノミーで絞りこむタクソノミーで絞りこむtax_queryの書き方はこちら

まとめ

  1. meta_querykey / value / compare / typeの4点セット。配列の中に条件の配列を入れる
  2. 数値比較には'type' => 'NUMERIC'が必須(既定は文字列比較で大小が狂う)
  3. 並べ替えはmeta_keyorderby: meta_value_num。値の無い投稿は消えるので注意
  4. 絞りこみの軸が決まっているなら、タクソノミー化してtax_queryのほうが速い

条件の書き方が身につくと、「データはあるのに一覧に出せない」という詰まりがなくなります。

よくある質問

meta_queryで数値の大小がおかしくなります
カスタムフィールドの値は文字列として保存されているため、typeを指定しないと文字列として比較されます('100'が'99'より小さいと判定されます)。'type' => 'NUMERIC'を付けてください。
カスタムフィールドの値で並べ替えるには?
'meta_key' => 'price' と 'orderby' => 'meta_value_num'(数値の場合)または'meta_value'(文字列の場合)を指定します。orderで昇順・降順を切り替えます。
値が入っていない投稿も含めて並べ替えたいです
meta_keyで並べ替えると、そのキーを持たない投稿は一覧から消えます。relationをORにしてNOT EXISTSの条件を足すか、投稿を保存するタイミングで既定値を入れておく方法があります。
meta_queryは重いと聞きました
投稿メタは1行1値のテーブルに入っているため、条件が増えるとJOINが増えて遅くなります。件数の多いサイトで絞りこみの軸が決まっているなら、カスタムタクソノミーにしてtax_queryで絞るほうが速いです。