查询多个帖子类型,每个帖子类型都有自己的元查询

时间:2015-05-08 作者:helgatheviking

我有两种帖子类型:假设productsproduct_variations. 我希望能够通过以下方式修改查询pre_get_posts 获取具有meta\\u密钥的所有产品"_visible" = "true""_available" = "true" 以及所有带有meta\\u密钥的product\\u变体"_featured" = "true".

product\\u变体没有meta\\u密钥"_visible"/"_available" 反之亦然AND meta\\u查询不返回任何结果。OR 关系也不太正确,因为有两个字段AND 则与一个职位类型相关OR 与其他岗位类型相关。

让它更直观,因为我刚刚意识到写出来有多么复杂:

**product**        
_visible = true      
_available = true

**product_variation**      
_featured = true
这是否可以通过查询参数实现
是否可以通过posts_where?
是否需要运行单独的查询,然后以某种方式合并结果?

2 个回复
SO网友:gmazzap

这是否可以通过查询参数实现?

我不这么认为。

是否可以通过\'posts_where\'?

使用一些可能是可行的\'posts_*\' 过滤器,不仅具有\'posts_where\'. 或者可能使用\'posts_request\' 筛选以完全删除查询。

我是否需要运行单独的查询,然后以某种方式合并结果?

这将是最简单的选择,也是最容易定制的,例如,很容易对产品使用限制,对产品变化使用不同的限制。

此外,这种方法在性能方面并不一定是最差的,因为如果单个查询非常复杂,那么并不总是有两个查询比单个查询慢。

第四种选择是构建一个完全定制的SQL。一个(经过模糊测试的)查询可能会起到以下作用:

$products_and_variations = $wpdb->get_results("
  SELECT * FROM (

    SELECT products.* FROM {$wpdb->posts} products
      LEFT JOIN {$wpdb->postmeta} meta1 ON meta1.post_id = products.ID
      LEFT JOIN {$wpdb->postmeta} meta2 ON meta2.post_id = products.ID
      WHERE products.post_type = \'product\'
      AND products.post_status = \'publish\'
      AND (meta1.meta_key = \'_visible\' AND meta1.meta_value = \'1\')
      AND (meta2.meta_key = \'_available\' AND meta2.meta_value = \'1\')
      GROUP BY products.ID

    UNION

    SELECT variations.* FROM {$wpdb->posts} variations
      LEFT JOIN {$wpdb->postmeta} meta3 ON meta3.post_id = variations.ID
      WHERE variations.post_type = \'product_variation\'
      AND variations.post_status = \'publish\'
      AND (meta3.meta_key = \'_featured\' AND meta3.meta_value = \'1\')
      GROUP BY variations.ID
  )
  posts
    ORDER BY post_date DESC
    LIMIT 0, 100
");
您可以注意到:

多么复杂,如何不可能对产品使用限制和对变化使用不同的限制:只能限制合并的结果在使用类似的方法之前,我会将其性能与2-querys方法进行比较,并仅在性能有明显改善的情况下使用自定义查询。

SO网友:Pieter Goosen

下面是另一种方法pre_get_posts.

使用get_posts() (x2个查询)以获取all 每个岗位类型的岗位ID符合其要求。添加fields 参数(\'fields\' => \'ids\') 只获取帖子ID,因为这是我们需要的,其他什么都不需要。这将大大提高性能,对资源也不会太苛刻。因此,您将得到两个post ID数组

现在,您需要将两个数组合并为array_merge() 创建一个“超级”数组,该数组将保存所有post ID

您可能希望将其保存在临时文件中,并在更新、丢弃、删除或发布帖子时刷新临时文件。这将确保不包含您网站的性能。

现在你有了一个符合你需要的ID数组,你可以把这个ID数组传递给post__in 在里面pre_get_posts

示例(未经测试,因为这只是一个示例。很遗憾,我没有时间进行正确的编码)

function get_all_special_posts()
{
     /*
     * This is here were you would want to introduce your transient
     */
    $args1 = [
        \'post_type\' => \'post_type_1\',
        \'fields\' => \'ids\',
        \'nopaging\' => true,
        \'meta_query\' => [[ /*Your specific custom fields */ ]]
    ];
    $query1 = get_posts( $args1 );

    $args2 = [
        \'post_type\' => \'post_type_2\',
        \'fields\' => \'ids\',
        \'nopaging\' => true,
        \'meta_query\' => [[ /*Your specific custom fields */ ]]
    ];
    $query2 = get_posts( $args2 );

    $post_ids = array_merge( $query1, $query2 );

    /*
     * Set your transient here, you would want to store $post_ids in the transient
     */

    return $post_ids;
}
记住创建一个函数,在发布、垃圾、取消刷新和更新时刷新瞬态。看看transition_post_status 为了这个。多功能挂钩。使用$post->post_type 仅针对您想要的两种职位类型

add_action( \'pre_get_posts\', function ( $q )
{
    if ( !is_admin() && $q->is_main_query() && $q->is_home() ) {
        $q->set( \'post__in\', get_all_special_posts() );
    }
});
请注意,我首先要检查get_all_special_posts() 实际上有一个有效数组,并且在将其传递给之前它不是空的post__in

结束

相关推荐

使用新的WP-Query()从循环中过滤后期格式;

嗨,我目前正在为我的博客构建一个主题。下面的代码指向最新的帖子(特色帖子)。因为这将有一个不同的风格比所有其他职位。然而我想过滤掉帖子格式:链接使用我在循环中定义的WP查询,因为它给我带来了更多的灵活性。我该怎么做呢? <?php $featured = new WP_Query(); $featured->query(\'showposts=1\'); ?> <?php while ($featured->have_post