按数字元键对查询结果进行排序,即使它不存在,但将带有元键的帖子放在第一位

时间:2020-04-25 作者:Álvaro Franz

我想订一份WP Query 由PHP中的数值元值生成的结果。

为了实现这一目标,我正在做以下工作:

$query->set( \'meta_query\', array(
    \'relation\' => \'OR\',
    array(
        \'key\' => \'orden_en_categ\', 
        \'compare\' => \'EXISTS\',
        \'type\'    => \'NUMERIC\'
    ),
    array(
        \'key\' => \'orden_en_categ\', 
        \'compare\' => \'NOT EXISTS\',
        \'type\'    => \'NUMERIC\'
    )
) );
$query->set(\'orderby\', \'meta_value_num\' );
$query->set(\'order\', \'ASC\');
调用元键的位置orden_en_categ.

And what is the problem?

此查询设置按以下顺序显示帖子:

发布without meta发布without meta和低值贴子我希望没有meta的帖子出现在有meta的帖子之后,如下所示:

具有meta和low值的帖子without meta发布without 元其中的职位顺序without meta并不重要。

The default meta solution:

我知道我可以在所有帖子中添加一个默认的meta,其值大约为999,这样就可以了。但是,必须有另一种方法,而不必添加那些粘性的元值。

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

首先,我想澄清一下,在正常情况下,没有具体的订单要求,并且假设您是在pre_get_posts hook,你可以这样做:

add_action(\'pre_get_posts\', function ($query) {
    // only perform for a given query
    // do your checks and return early
    if (! $query->is_main_query() || ! $query->is_home()) {
        return;
    }

    $query->set(\'meta_key\', \'orden_en_categ\');
    $query->set(\'orderby\', \'meta_value_num\');
    $query->set(\'order\', \'ASC\');
});
根本不需要设置元查询。

然后,要实现最后为空的升序,有不同的方法。假设数据是数字,可以使用减号运算符并按如下顺序降序:

add_filter(\'posts_orderby\', function ($orderby, $query) {
    global $wpdb;

    // only perform for a given query
    // do your checks and return early
    if (! $query->is_main_query() || ! $query->is_home()) {
        return $orderby;
    }

    return "-{$wpdb->postmeta}.meta_value DESC";
}, 2, 10);
字母数字值的更通用解决方案可以是:

add_filter(\'posts_orderby\', function ($orderby, $query) {
    global $wpdb;

    // return early...

    return "{$wpdb->postmeta}.meta_value IS NULL, {$wpdb->postmeta}.meta_value ASC";
}, 2, 10);
IS NULL 为空值返回1,为非空值返回0。按升序,0(不是null)将排在第一位。然后我们也按值本身的升序排序。

最后,当使用posts_orderby 过滤器,您不再需要这两行:

$query->set(\'orderby\', \'meta_value_num\');
$query->set(\'order\', \'ASC\');
Edit: 最初的解决方案没有考虑到不存在的元值。去除meta_key, meta_query, orderbyorder 从查询变量pre_get_posts 并按如下方式过滤查询。

add_filter(\'posts_clauses\', function ($clauses, $query) {
    global $wpdb;

    if (!$query->is_main_query() || !$query->is_home()) {
        return $clauses;
    }

    $meta_key = \'orden_en_categ\';

    $clauses[\'join\'] .= " LEFT JOIN {$wpdb->postmeta} ON ({$wpdb->posts}.ID = {$wpdb->postmeta}.post_id AND {$wpdb->postmeta}.meta_key = \'$meta_key\')";
    $clauses[\'where\'] .= " AND ({$wpdb->postmeta}.meta_key = \'$meta_key\' OR {$wpdb->postmeta}.post_id IS NULL)";
    $clauses[\'groupby\'] = "{$wpdb->posts}.ID";
    $clauses[\'orderby\'] = "-{$wpdb->postmeta}.meta_value+0 DESC";

    return $clauses;
}, 2, 10);
几乎是一个完整的自定义查询,但无法找到更好的方法。希望有帮助。

生成的查询类似于:

SELECT wp_posts.ID
FROM wp_posts
LEFT JOIN wp_postmeta
   ON (wp_posts.ID = wp_postmeta.post_id AND wp_postmeta.meta_key = \'orden_en_categ\')
WHERE 1=1
   AND wp_posts.post_type = \'post\'
   AND (wp_posts.post_status = \'publish\')
   AND (wp_postmeta.meta_key = \'orden_en_categ\' OR wp_postmeta.post_id IS NULL)
GROUP BY wp_posts.ID
ORDER BY -wp_postmeta.meta_value+0 DESC
LIMIT 0, 10

相关推荐

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

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