是否使用WP_QUERY查询多个类别,每个类别的帖子数量有限?

时间:2010-08-25 作者:Amit

我有3个类别,每个类别有15篇帖子,我想向db做一个查询,每个类别只有5篇第一篇帖子,我怎么做?

$q = new WP_Query(array( \'post__in\' => array(2,4,8), \'posts_per_page\' => **FIRST_5_OF_EACH_CAT** ));
如果不可能,那么获取父类别的所有帖子并循环浏览它们或创建3个不同的查询,哪种方式更有效?

3 个回复
最合适的回答,由SO网友:MikeSchinkel 整理而成

你想要的是可能的,但需要你深入研究SQL which I like to avoid whenever possible (不是因为我不知道,我是一名高级SQL开发人员,而是因为in WordPress you want to use the API whenever possible 尽量减少与未来潜在数据库结构更改相关的未来兼容性问题。)

带有UNION 运算符可以使用SQL,您需要的是UNION 在您的查询中,假设您的类别slug是"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
)
可以将SQL UNION与posts_join 使用上面的过滤器,您可以just make the call directly 或者你可以use a posts_join filter hook 如下所示:;注意,我使用的是PHP heredoc 所以要确保SQL; 左对齐。还请注意,我使用了一个全局变量,通过在数组中列出类别slug,可以定义钩子之外的类别。您可以将此代码放入插件或主题的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 只有在需要时才使用它,测试标准可能很棘手。

而是专注于优化

然而,我想你的问题是more about optimization 比能够进行前5次3次查询要好得多,对吗?如果是这样,那么可能还有其他使用WordPress API的选项?

更好地使用瞬态API进行缓存

我想你的帖子不会经常改变,对吧?如果您定期接受三(3)次查询命中,然后使用Transients API? 您将获得可维护的代码和出色的性能;比UNION 因为WordPress将把帖子列表作为序列化数组存储在wp_options 桌子

您可以采用以下示例,并将其作为test.php 要对此进行测试,请执行以下操作:

<?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 相反

希望这有帮助?

SO网友:hakre

WP_Query() 不支持每种类别的首个X。而不是WP_Query() 您可以使用get_posts() 在每个类别上,可以说是三次:

<?php
$posts      = array():
$categories = array(2,4,8);
foreach($categories as $cat) {
  $posts[] = get_posts(\'numberposts=5&offset=1&category=\'.$cat);
}
?>
$posts 现在包含每个类别的前五个帖子。

SO网友:Bernard Chen

我不知道如何在单个查询中获得每个类别的前五篇帖子。如果你的帖子只有45篇,那么点击数据库一次,每个类别获得5篇帖子可能是最有效的方法。但是,三次访问数据库并将结果合并并不是一件坏事。

结束

相关推荐