[wp-trac] [WordPress Trac] #42907: Meta Queries: support ordering by meta_value but still including items without that key
WordPress Trac
noreply at wordpress.org
Thu Dec 14 21:54:49 UTC 2017
#42907: Meta Queries: support ordering by meta_value but still including items
without that key
-------------------------+-----------------------------
Reporter: jdgrimes | Owner:
Type: enhancement | Status: new
Priority: normal | Milestone: Awaiting Review
Component: Query | Version: trunk
Severity: normal | Keywords:
Focuses: |
-------------------------+-----------------------------
Consider this scenario:
- You want to order a query's results by `meta_value` of a particular
`meta_key`.
- Not all items have that key/value pair set.
- You want to still include those items in the results.
- You want them to be ordered as if the `meta_value` is `NULL` (or `0` if
using `meta_value_num`).
There is currently no way to do this. (But it is a desired feature, see
[https://wordpress.stackexchange.com/questions/28409/way-to-include-posts-
both-with-without-certain-meta-key-in-args-for-wp-query 1]
[https://wordpress.stackexchange.com/questions/102447/sort-on-meta-value-
but-include-posts-that-dont-have-one?noredirect=1&lq=1 2]
[https://stackoverflow.com/questions/17016770/wordpress-order-by-meta-
value-if-it-exists-else-date 3].)
If you don't care about the items that don't have the meta key set being
included, then you can use `compare` => `EXISTS`.
{{{#!php
<?php
$query = new WP_Query(
array(
'orderby' => 'meta_value',
'meta_query' => array(
array(
'key' => 'test',
'compare' => 'EXISTS',
),
),
)
);
}}}
However, that won't work if we want to include results where the key/value
pair doesn't exist.
A workaround is to do something like this:
{{{#!php
<?php
$query = new WP_Query(
array(
'orderby' => 'meta_value',
'meta_query' => array(
'relation' => 'OR',
array(
'key' => 'test',
'compare' => 'EXISTS',
),
array(
'key' => 'test',
'compare' => 'NOT EXISTS',
),
),
)
);
}}}
This approach solves the problem of the items with no key/value pair not
being included. However, it does not order those items in the results
reliably. Instead of the `meta_value` being interpreted as `null` (which
we might expect), the database will choose another `meta_value` entry for
that item to order that item based on.
My proposal is to add a `NONE` option for `compare`, so that it would be
possible to achieve the desired ordering with a query like this:
{{{#!php
<?php
$query = new WP_Query(
array(
'orderby' => 'meta_value',
'meta_query' => array(
'relation' => 'OR',
array(
'key' => 'test',
'compare' => 'NONE',
),
),
)
);
}}}
This would result in a query that included a `LEFT JOIN` on the meta table
for that `meta_key`, but did not include any conditions in the query.
(This is basically a `NOT EXISTS` query but without the `ID = NULL`
requirement, so that it is just a left join and not a left outer join.)
When using `meta_value_num` in particular though, ordering by `NULL` may
not be desirable (those results will be after all other results); `0` may
be preferred as the imputed value (consider a case when negative values
are present). To make this possible, I suggest allowing the clause to also
specify a `default` value, which will be used in the `ORDER BY` clause
with `COALESCE`.
Initial patch forthcoming.
--
Ticket URL: <https://core.trac.wordpress.org/ticket/42907>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list