order&orderbyのドキュメント を読んでみると、複数のmeta_key
値に基づく注文のサポートがあるかどうかは私には明らかではありません。
明らかに、meta_query
を使用して、複数のキーと値のペアに基づいて投稿を返すことができますが、これらの結果が複数のmeta_keys
に基づいて返される順序を制御できるようにしたいです。
たとえば、複数のカテゴリがあり、各カテゴリにランクがあるページがあります。ユーザーが3つの異なるカテゴリのいずれかにあるページを検索している場合は、必要な投稿すべてを次のように返します。
$query = array(
'order' => 'DESC',
'orderby' => 'meta_value_num',
'meta_query' => array(
'relation' => 'OR',
array( 'key' => 'cat1', 'type' => 'numeric' ),
array( 'key' => 'cat2', 'type' => 'numeric' ),
array( 'key' => 'cat3', 'type' => 'numeric' )
);
);
ただし、それらが返されたら、結果が返されたカテゴリのいずれか1つにわたる最も高い数値に基づいてそれらが順序付けられるようにします。つまり、9
の値がcat1
の投稿は、9
の値がcat3
の投稿とほぼ同じ順序で表示されます。
この答えを見てmeta_key
は'orderby' => 'meta_value_num'
には必要ないと思われますが、それはmeta_value
のドキュメントとは一致しません。 meta_value_num
...より明確に説明されています。ありがとうございます。
'orderby'と 'meta_query'についてのWP 4.2のクエリの改善点を確認してください。詳細は https://make.wordpress.org/core/2015/03/30/query-improvements-in-wp-4-2-orderby-and-meta_query .
Meta_query句に名前を付けて、順番に並べるようにしてください。
次のコードはテストされていません。
$query = array(
'order' => 'DESC',
'meta_query' => array(
'relation' => 'OR',
'cat1-clause' => array( 'key' => 'cat1', 'type' => 'numeric' ),
'cat2-clause' => array( 'key' => 'cat2', 'type' => 'numeric' ),
'cat3-clause' => array( 'key' => 'cat3', 'type' => 'numeric' )
);
'orderby' => array(
'cat1-clause' => 'ASC',
'cat2-clause' => 'ASC',
'cat3-clause' => 'ASC',
),
);
WP_Queryのget_postsメソッドを見ると、posts_request
フィルタに渡された変数を出力することでSQLをデバッグするのは簡単です。
// Debug the WP_Query sql
add_filter( 'posts_request', function( $sql ) {
echo "<pre>";
var_dump( $sql );
echo "</pre>";
return $sql;
} );
結果は次のようになります。
string(426) "SELECT SQL_CALC_FOUND_ROWS wp_posts.* FROM wp_posts INNER JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id ) WHERE 1=1 AND wp_posts.post_type = 'post' AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private') AND (
wp_postmeta.meta_key = 'cat1'
OR
wp_postmeta.meta_key = 'cat2'
OR
wp_postmeta.meta_key = 'cat3'
) GROUP BY wp_posts.ID ORDER BY wp_postmeta.meta_value+0 DESC LIMIT 0, 10"
クエリは最初は正しく見えるかもしれませんが、そうではありません。 meta_value
句には、内部結合の最初の行からORDER BY
を使用します。この場合、それは'cat1'
です。この振る舞いを変更するには、posts_orderby
フックを使用してORDER BY
ステートメントを変更し、MAX
mysql関数を使用して、最初の行だけでなくすべてのmeta_valuesの最大値を使用するようにします。
// Filter to alter the orderby sql
function nvdGMCWh_alter_posts_orderby( $sql ) {
return "MAX( $wpdb->postmeta.meta_value+0 ) DESC";
} // - alter_posts_orderby
// Register the filter
add_filter( 'posts_orderby', 'nvdGMCWh_alter_posts_orderby' );
// The WP_Query
$res = new WP_Query;
$args = [
'order' => 'DESC',
'orderby' => 'meta_value_num',
'meta_query' => [
'relation' => 'OR',
['key' => 'cat1', 'type' => 'numeric'],
['key' => 'cat2', 'type' => 'numeric'],
['key' => 'cat3', 'type' => 'numeric'],
],
]; // - $args
// Execute the query and get the results
$result = $res->query( $args );
// Clean up the filter so it won't affect later queries
remove_filter( 'posts_orderby', 'nvdGMCWh_alter_posts_orderby' );
// Loop through the results
foreach ( $result as $post ) {
// ... code here
} // - foreach