How can I use order_by to order by two meta_keys without excluding posts that don't have those keys initialized?

I have two meta_keys on a custom post type. I want to be able to query all of these posts, and order them by the two meta_key, one taking precedence over the other.

I.e. I have one meta_key called stickied, these should always appear first. The second meta_key is popularity, which is a basic hit count for that post.

When I use meta_query, it seems that posts without the meta keys initialized will not appear in the result set. I want all posts regardless of whether they have the meta_key initialized or not, and then order them based on those meta_key.

Is this possible?

Solutions Collecting From Web of "How can I use order_by to order by two meta_keys without excluding posts that don't have those keys initialized?"

As I understand, you are trying to sort the post by meta values. In such cases, you can use 'orderby => 'meta_value'. So your query will look like this:

$args = array(
    'orderby'   => 'meta_value',
    'meta_key'  => 'stickied',
);
$query = new WP_Query( $args );

Not that orderby can accept multiple values, such as:

$args = array(
    'post_type' => 'page',
    'orderby'   => array( 'title' => 'DESC', 'meta_value' => 'ASC' ),
    'meta_key'  => 'stickied',

);

However I’m not sure if you can use multiple meta values, but it is probably possible. At the moment I don’t have such condition in my database to test it, but based on my example and this codex page you should be able to easily try it out.

Please let me know if sorting by multiple values worked for you based on above structure.

UPDATE

After digging for a while, I’ve found this answer and this code that provides a solution to this situation:

$args = array(
    'post_type' => 'post',
    'orderby' => 'meta_key',
    'order' => 'ASC',
    'meta_query' => array(
        'relation' => 'OR',
        array( 
            'key'=>'stickied',
            'compare' => 'EXISTS'           
        ),
        array( 
            'key'=>'popularity',
            'compare' => 'EXISTS'           
        )
    ),
    'post_per_page'=>-1
);

$query = new WP_Query($args);