質問: new wp_query(array( 'post__in' => array(2,4,8), 'posts_per_page' => **first_5_of_each_cat** )); それが不可能な場合、何がより効率的ですか?親カテゴリのすべての投稿を取得してそれらをループするか、3つの異なるクエリを作成する?
回答: あなたが望むものは可能ですが、可能であればいつでも避けたいsqlを掘り下げる必要があります(私はそれを知らないからではなく、私はm高度なsql開発者。ただし、wordpressのでは、可能な限りapiを使用するため、将来に関連する将来の互換性の問題を最小限に抑えたい潜在的なデータベース構造の変更。)union演算子を使用したsqlは可能性ですsqlを使用するには、クエリでunion演算子を使用します。カテゴリスラグが"category-1"、"category-1"、および"category-3"であると仮定すると、次のようになります。select * from wp_posts where id in ( select tr.object_id from wp_terms t inner join wp_term_taxonomy tt on t.term_id = tt.term_id inner join wp_term_relationships tr on tt.term_taxonomy_id = tr.term_taxonomy_id where tt.taxonomy='category' and t.slug='category-1' limit 5 union select tr.object_id from wp_terms t inner join wp_term_taxonomy tt on t.term_id = tt.term_id inner join wp_term_relationships tr on tt.term_taxonomy_id = tr.term_taxonomy_id where tt.taxonomy='category' and t.slug='category-2' limit 5 union select tr.object_id from wp_terms t inner join wp_term_taxonomy tt on t.term_id = tt.term_id inner join wp_term_relationships tr on tt.term_taxonomy_id = tr.term_taxonomy_id where tt.taxonomy='category' and t.slug='category-3' limit 5 ) posts_joinフィルターでsql unionを使用できます上記を使用して、単に直接呼び出しを行うか、posts_joinフィルターフックを使用することができます次のように。 php heredoc を使用していることに注意してください。したがって、sql;が左にフラッシュされることを確認してください。また、グローバル変数を使用して、配列内のカテゴリスラッグをリストすることにより、フックの外側でカテゴリを定義できるようにしました。このコードをプラグインまたはテーマのfunctions.phpファイルに配置できます。<?php global $top_5_for_each_category_join; $top_5_for_each_category_join = array('category-1','category-2','category-3'); add_filter('posts_join','top_5_for_each_category_join',10,2); function top_5_for_each_category_join($join,$query) { global $top_5_for_each_category_join; $unioned_selects = array(); foreach($top_5_for_each_category_join as $category) { $unioned_selects[] =<<<sql select object_id from wp_terms t inner join wp_term_taxonomy tt on t.term_id = tt.term_id inner join wp_term_relationships tr on tt.term_taxonomy_id = tr.term_taxonomy_id where tt.taxonomy='category' and t.slug='{$category}' limit 5 sql; } $unioned_selects = implode("\n\nunion\n\n",$unioned_selects); return $join . " inner join ($unioned_selects) categories on wp_posts.id=categories.object_id " ; } しかし、副作用がありますもちろん、posts_joinのようなクエリ変更フックを使用すると、常にクエリに対してグローバルに動作するという副作用が生じるため、通常は、必要なときにのみ使用するifで変更をラップする必要がありますテストするのは難しい場合があります。代わりに最適化に焦点を当てますか?しかし、私はあなたの質問が懸念していると思います最適化についての詳細、トップ5の3回のクエリを行うことができるということよりも正しいですか?その場合、wordpress apiを使用する他のオプションがありますか?キャッシュにtransients apiを使用した方が良いですか?あなたの投稿はそれほど頻繁には変わらないと思いますか? 3つのクエリヒットを定期的に受け入れ、 transients api を使用して結果をキャッシュするとどうなりますか?保守可能なコードと優れたパフォーマンスが得られます。 wordpressは投稿のリストをwp_optionsテーブルの1つのレコードにシリアル化された配列として保存するため、上記のunionクエリよりもかなり優れています。次の例を使用し、test.phpとしてwebサイトのルートにドロップして、これをテストできます。<?php $timeout = 4; // 4 hours $categories = array('category-1','category-2','category-3'); include "wp-load.php"; $category_posts = get_transient('top5_posts_per_category'); if (!is_array($category_posts) || count($category_posts)==0) { echo "hello every {$timeout} hours!"; $category_posts = array(); foreach($categories as $category) { $posts = get_posts("post_type=post&numberposts=5&taxonomy=category&term={$category}"); foreach($posts as $post) { $category_posts[$post->id] = $post; } } set_transient('top5_posts_per_category',$category_posts,60*60*$timeout); } header('content-type:text/plain'); print_r($category_posts); 概要はい、sql unionクエリとposts_joinフィルターフックを使用して要求したことを実行できますが、transients api代わりに。お役に立てれば?