The reason you’re only getting those users that have that meta_key is because you’re include 'meta_key' => '...'
in $args
. That limits results to those that have that key, regardless of any clauses you may have in a meta_query
. This applies to WP_Query
, WP_User_Query
and WP_Comment_Query
.
Starting in WP 4.2, you can “name” the clauses in a meta_query
and then use those “names” in the orderby
clause, see Query improvements in WP 4.2: ‘orderby’ and ‘meta_query’. Unfortunately, the code reference and codex entries for WP_Query
and WP_User_Query
haven’t been updated to reflect this, altho WP_Meta_Query does cover it.
So, you can ALMOST get what you’re after with the following:
$args = array (
'role' => 'my_staff_role',
'fields' => 'all',
'meta_query' => array (
'relation' => 'OR',
'exists' => array (
'key' => 'staff_profile_position',
'compare' => 'EXISTS',
// 'type' => 'NUMERIC',
),
'not_exists' => array (
'key' => 'staff_profile_position',
'compare' => 'NOT EXISTS',
),
),
'orderby' => 'exists not_exists',
) ;
Note: To mimic 'orderby' => 'meta_value_num'
(as you have in your question) you would have to include 'type' => 'NUMERIC'
in the meta_query
clauses. However, that causes all of users without to sort to the top, instead of the bottom (which is why I have it commented out above).
Thus, if you can live with having those users with your meta_key to be ordered by that key treated as a string, rather than a number, then the above will do.
If you can’t, then you’ll have to do 2 separate queries (one for those users with the meta_key, ordered numerically by that key, and one for those users without the meta_key) and merge the results of those 2 queries.