私の投稿の一部(全部ではありません)はメタキー/値としての価格を持っています。今日、私はpre_get_posts
アクションを使用して、ユーザーが特定の値の範囲内にある価格を検索できるようにします。
これは私が今日使用しているコードです、そしてそれは働いています。
add_action('pre_get_posts', 'my_search_price');
function my_search_price( $query ) {
if ($query->get('maxprice') != "" && $query->get('minprice') != "" && $query->is_main_query()) {
$maxprice = intval($query->get('maxprice'));
$minprice = intval($query->get('minprice'));
$meta = array();
$meta[] =
array (
'key' => 'price',
'value' => $maxprice,
'compare' => '<=',
'type' => 'numeric'
);
$meta[] =
array (
'key' => 'price',
'value' => $minprice,
'compare' => '>=',
'type' => 'numeric'
);
$meta[] =
array (
'key' => 'price_updated',
'value' => time()-(60*60*24*14),
'compare' => '>',
'type' => 'numeric'
);
$query->set('meta_query', $meta);
}
}
私の問題は、投稿の中には2番目の値段を持つものもあり、これもメタキー/値として格納されています。新しい価格の名前は "price_used"で、この価格には "price_used_updated"という名前の独自の更新されたキー/値があります。
新しい価格も処理できるように、関数my_search_price()
を変更したいと思います。結果は、 "price" OR "price_used"がminpriceとmaxpriceの間にある投稿になります。 "price_updated"/"price_used_updated"は最長14日でなければなりません。
他の記事を読んで理解したように、meta_queryはネストできません。だから私は代わりにposts_joinまたは/そしてposts_whereフィルタを使ってSQLを修正する必要があります。
誰かが解決策への正しい方向を教えてください。私はもっと高度なmeta_queryが必要な最初の人ではないと思います。しかし、私は以前にSQLクエリを修正したことがありません。
私がしたことはこれらのページを読むことです:
更新:結果クエリは次のようになります。
SELECT SQL_CALC_FOUND_ROWS wp_posts.*, mtGP2.meta_value, mtAM2.meta_value
FROM wp_posts
INNER JOIN wp_postmeta AS mtGP1 ON (wp_posts.ID = mtGP1.post_id)
INNER JOIN wp_postmeta AS mtGP2 ON (wp_posts.ID = mtGP2.post_id)
INNER JOIN wp_postmeta AS mtAM1 ON (wp_posts.ID = mtAM1.post_id)
INNER JOIN wp_postmeta AS mtAM2 ON (wp_posts.ID = mtAM2.post_id)
WHERE 1=1
AND wp_posts.post_type = 'post'
AND wp_posts.post_status = 'publish'
AND
(
(mtGP1.meta_key = 'price' AND CAST(mtGP1.meta_value AS SIGNED) BETWEEN 1 AND 10
AND mtGP2.meta_key = 'price_updated' AND CAST(mtGP2.meta_value AS SIGNED) > NOW()-60*60*24*14)
OR
(mtAM1.meta_key = 'price_used' AND CAST(mtAM1.meta_value AS SIGNED) BETWEEN 1 AND 10
AND mtAM2.meta_key = 'price_used_updated' AND CAST(mtAM2.meta_value AS SIGNED) > NOW()-60*60*24*14)
)
GROUP BY wp_posts.ID
しかし、このクエリには2つの問題があります。
1)とても遅い
2)私はまだ問題を抱えています、なぜなら私はどのようにしてwordpressで問い合わせを実行するのかわからないからです。私はpost_whereとposts_joinフィルタを使う必要があると思いますが、その方法がわからない。
UPDATE2。私はそれがもはや遅くないようにクエリを書き直しました。しかし、私はまだ(私のオリジナルのmy_search_price()関数のように)フィルタやアクションを使ってwordpressでクエリを実装する方法を知りません。
SELECT SQL_CALC_FOUND_ROWS *
FROM
(
SELECT wp_posts.*
FROM wp_posts
INNER JOIN wp_postmeta AS mtGP1 ON (wp_posts.ID = mtGP1.post_id)
INNER JOIN wp_postmeta AS mtGP2 ON (wp_posts.ID = mtGP2.post_id)
WHERE 1=1
AND wp_posts.post_type = 'post'
AND wp_posts.post_status = 'publish'
AND mtGP1.meta_key = 'price'
AND CAST(mtGP1.meta_value AS SIGNED) BETWEEN 1 AND 10
AND mtGP2.meta_key = 'app_updated'
AND CAST(mtGP2.meta_value AS SIGNED) > UNIX_TIMESTAMP()-60*60*24*14
GROUP BY wp_posts.ID
UNION
SELECT wp_posts.*
FROM wp_posts
INNER JOIN wp_postmeta AS mtGP1 ON (wp_posts.ID = mtGP1.post_id)
INNER JOIN wp_postmeta AS mtGP2 ON (wp_posts.ID = mtGP2.post_id)
WHERE 1=1
AND wp_posts.post_type = 'post'
AND wp_posts.post_status = 'publish'
AND mtGP1.meta_key = 'price_used'
AND CAST(mtGP1.meta_value AS SIGNED) BETWEEN 1 AND 10
AND mtGP2.meta_key = 'price_used_updated'
AND CAST(mtGP2.meta_value AS SIGNED) > UNIX_TIMESTAMP()-60*60*24*14
GROUP BY wp_posts.ID
) AS t
UNION
をWP_Query
で動作させる方法を概説します。
add_filter(
'posts_request',
function ($clauses) {
$clauses = str_replace('SQL_CALC_FOUND_ROWS','',$clauses,$scfr);
$scfr = (0 < $scfr) : 'SQL_CALC_FOUND_ROWS' : '';
$clause2 = $clauses; // manipulate this
return "SELECT {$scfr} u.* FROM (({$clauses}) UNION ({$clause2})) as u";
},
1,
2
);
WP_Query
引数を設定してUNION
の前半を生成し、それからそれを操作してクエリ全体を作成します。このようなものは近いはずです。
add_action('pre_get_posts', 'my_search_price');
function my_search_price( $query ) {
if ($query->get('maxprice') != "" && $query->get('minprice') != "" && $query->is_main_query()) {
$maxprice = intval($query->get('maxprice'));
$minprice = intval($query->get('minprice'));
$meta = array();
$meta[] =
array (
'key' => 'price',
'value' => array($maxprice,$minprice),
'compare' => 'between',
);
$meta[] =
array (
'key' => 'app_updated',
'value' => time()-(60*60*24*14),
'compare' => '>',
'type' => 'numeric'
);
$query->set('meta_query', $meta);
}
}
add_filter(
'posts_request',
function ($clauses) {
$clauses = str_replace('SQL_CALC_FOUND_ROWS','',$clauses,$scfr);
$scfr = (0 < $scfr) ? 'SQL_CALC_FOUND_ROWS' : '';
$clause2 = str_replace('price','price_used',$clauses); // manipulate this
$clause2 = str_replace('app_updated','price_used_updated',$clauses);
return "SELECT {$scfr} u.* FROM (({$clauses}) UNION ({$clause2})) as u";
},
1,
2
);
望まないときに実行されないように、post_requests
フィルタにロジックを追加する必要があります。