一个查询中的WP_QUERY ORDERBY定制字段,然后是POST_DATE

时间:2018-08-12 作者:londonfed

我需要按自定义字段订购前三篇文章,然后按post_date 在一个查询中-例如:

第4篇(field_order: 1) 第3篇(field_order: 2) 第2篇(field_order: 3) 第1篇(field_order: 空)

  • 发布0(field_order: 空)
  • Post 1Post 0 需要订购者post_date.

    我可以很容易地按自定义字段排序,但当我添加一篇没有自定义字段的帖子(帖子1和0)时,它不会出现在查询中。

    以下是我当前正在尝试的查询:

        $args = array(
            \'post_type\' => \'insights\',
            \'posts_per_page\' => \'9\',
            \'meta_query\' => array(
                array(
                    \'key\' => \'field_order\',
                    \'value\'   => \'0\',
                    \'compare\' => \'>\'
                )
            ),
            \'orderby\' => array(
                \'field_order\' => \'ASC\',
                \'post_date\' => \'ASC\',
            ),
            \'order\' => \'ASC\'
        );
    

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

    多个meta_query 与的参数OR

    您可以使用\'relation\' => \'OR\' 中的参数meta_query 有两套field_order 参数:一个meta_value >= \'0\' 另一个是NOT EXISTS 生成主查询。

            \'meta_query\'     => array(
                \'relation\'   => \'OR\',
                field_order\' => array(
                    \'key\'       => \'field_order\',
                    \'value\'     => \'0\',
                    \'compare\'   => \'>=\',
                    \'type\'      => \'NUMERIC\'
                ),  
                \'field_order_withnulls\' => array(
                    \'key\'       => \'field_order\',
                    \'compare\'   => \'NOT EXISTS\',
                    \'type\'      => \'NUMERIC\'
                )
            )
    
    我们可以使用\'field_order_withnulls\' => \'ASC\', 但是,由于左连接,将有null field_order 值(&A);这些将出现在数字之前field_order 中的值ASC 订货人。

    为了解决这个问题,我们将使用ORDER BY -field_order DESC 如上所述的技巧here.

    这将通过反转来纠正顺序DESCASC, 但保持与null 数值后的值。

    实施- (反向)运算符输入orderby- (反向)运算符输入orderby. 因此,我们将引入一个自定义WP_Query 名为的属性_inverse_order 然后使用posts_orderby 筛选以实现它。

    示例代码:

        // posts_orderby filter callback function
        // place this function in theme\'s functions.php file or in a custom plugin
        function wpse311227_inverse_orderby( $orderby, $query ) {
            remove_filter( \'posts_orderby\', \'wpse311227_inverse_orderby\', 10, 2 );
            $idx = (int) $query->get( \'_inverse_order\' ) - 1;
            if( $idx >= 0 ) {
                $orders = preg_split( "/(?<=ASC|DESC),[\\s]*/i", $orderby );
                if( $idx < count( $orders ) ) {
                    $orders[$idx] = \'-\' . $orders[$idx];
                }
                return implode( $orders, \', \' );
            }
    
            return $orderby;
        }
    
    
        // adding the posts_orderby filter to implement the custom \'_inverse_order\' attribute
        // this should be placed just before the WP_Query call
        add_filter( \'posts_orderby\', \'wpse311227_inverse_orderby\', 10, 2 );
        $args = array(
            \'post_type\'      => \'insights\',
            \'posts_per_page\' => \'9\',
            \'meta_query\'     => array(
                \'relation\'   => \'OR\',
                field_order\' => array(
                    \'key\'       => \'field_order\',
                    \'value\'     => \'0\',
                    \'compare\'   => \'>=\',
                    \'type\'      => \'NUMERIC\'
                ),  
                \'field_order_withnulls\' => array(
                    \'key\'       => \'field_order\',
                    \'compare\'   => \'NOT EXISTS\',
                    \'type\'      => \'NUMERIC\'
                )
            ),
            \'orderby\' => array(
                \'field_order_withnulls\' => \'DESC\',
                \'post_date\'             => \'ASC\'
            ),
            // this custom attribute is implemented in wpse311227_inverse_orderby() function
            // to correct the ordering by placing a \'-\' operator
            // value of _inverse_order attribute is the position of the
            // orderby attribute to be be inversed,
            // (position starts with 1)
            // in this case, since: \'field_order_withnulls\' => \'DESC\'
            // is in position 1 of \'orderby\' attribute array, so:
            \'_inverse_order\'  => 1
        );
        $query = new WP_Query( $args );
    
    这将生成具有field_order > 0 还有那些没有field_order 具有预期顺序的元数据。

    Note:您需要传递一个非空value 在里面meta_query 对于NOT EXISTS 检查WordPress版本是否低于3.9。检查此项note from codex:

    由于bug#23268,在3.9之前,不存在比较需要值才能正常工作。必须为value参数提供一些字符串。空字符串或NULL无效。但是,任何其他字符串都可以做到这一点,并且在使用NOT EXISTS时不会显示在SQL中。


    Warning:WP_Query 将使用两个LEFT JOIN, 这不是很有效。虽然,即使是几千篇帖子,这也是可以忍受的。我已经测试了15000多篇帖子;查询平均耗时约0.3秒。然而,如果你有数百万甚至数十万篇帖子,那么你必须优化查询或找到更有效的方法来获得相同的结果。

    SO网友:nmr

    我不确定是否可以在WP_Query, 但这应该是可行的:

    global $wpdb;
    $sql = "SELECT p.* FROM {$wpdb->posts} p "
        . " LEFT JOIN {$wpdb->postmeta} pm ON p.id=pm.post_id AND pm.meta_key=\'field_order\' "
        . " WHERE p.post_type=\'insights\' AND p.post_status=\'publish\' "
            . " AND (pm.meta_value > 0 OR pm.meta_value IS NULL) "
        . " ORDER BY -pm.meta_value DESC, p.post_date ASC LIMIT 9";
    $posts = $wpdb->get_results($sql);
    

    结束

    相关推荐

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

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