0

I want to list jobs (jobs are custom post types) in country order. The country to prioritise in the resultset is defined by the user in the WP CMS. With the configured country being listed first I then want to control the ordering of the remaining rows.

e.g. if they select 'gb' I want the resultset to look something like this:

gb 
gb 
au 
es 
fr 
sw 
sw

I need to use pre_get_posts to achieve this. Hopefully that all makes sense.

Here is what I have just now. I've hard-coded the key/value for readability rather than display the CMS classes / values.

        add_action(
            'pre_get_posts',
            function(WP_Query $query) {
                if ($query->is_main_query()) {
                    $country_order = array(
                        'meta_query' => array(
                            array (
                                'key' => 'job_country',
                                'value' => 'gb',
                                'compare' => '=' 
                            )
                        )
                    );
                    $query->set('meta_query', $country_order);
                }
            }
        );

This returns only 'gb' and none of the others and I'm a bit stuck as to where to go from here. Any help will be much appreciated.

Update: based on Tom's comments here's some code to achieve what I wanted after using $working_list to order things how I needed them. The custom post type in this case is 'job'.

        $args = array(
            'post_type' => 'job',
            'posts_per_page' => -1,
            'post__in' => $working_list,
            'orderby' => 'post__in'
        );

        return get_posts($args);

So $working_list essentially contains an array of post IDs all in the correct order thanks to some non-Wordpress specific PHP coding. Without the 'orderby' => 'post__in' element in $args the order of the posts returned in get_posts() was inconsistent.

2
  • I'm not sure that this can be done with a single WP_Query and the database, you'll need multiple post queries which won't scale with pagination. Additionally, you should not us post meta to store the job_country if you intend to filter by it, that's what taxonomies are for and it will carry a hefty performance cost that gets larger as your site increases in size
    – Tom J Nowell
    Oct 13 '21 at 11:13
  • I would also note that meta_query is not used for sorting/ordering, it's used for filtering. The filter in the question also doesn't exclude REST/non job queries/RSS/WP Admin/etc
    – Tom J Nowell
    Oct 13 '21 at 11:15
0

This isn't possible with WP_Query. To achieve your goal multiple queries are necessary, one for each country, with the results fetched separately then combined in PHP manually.

You also can't use meta_query to sort, meta_query is for filtering/searching post meta, which is very expensive and gets slower as your meta table gets larger. Post meta is optimised for get_post_meta, fetching values when you already know the post ID/key. It was never intended for searching/filtering for posts by value, that's why taxonomies were added.

If you want to change the sorting to use meta, refer to the sorting official docs, which show that you can sort by meta_value or meta_value_num for a single key ( meta_value_key ), defined using meta_key_value and orderby, with a limited number of options for how to sort:

‘meta_value‘ – Note that a ‘meta_key=keyname‘ must also be present in the query. Note also that the sorting will be alphabetical which is fine for strings (i.e. words), but can be unexpected for numbers (e.g. 1, 3, 34, 4, 56, 6, etc, rather than 1, 3, 4, 6, 34, 56 as you might naturally expect). Use ‘meta_value_num‘ instead for numeric values. You may also specify ‘meta_type‘ if you want to cast the meta value as a specific type. Possible values are ‘NUMERIC’, ‘BINARY’, ‘CHAR’, ‘DATE’, ‘DATETIME’, ‘DECIMAL’, ‘SIGNED’, ‘TIME’, ‘UNSIGNED’, same as in ‘$meta_query‘. When using ‘meta_type’ you can also use ‘meta_value_*’ accordingly. For example, when using DATETIME as ‘meta_type’ you can use ‘meta_value_datetime’ to define order structure.

Listing the values and a priority or order they go in is not possible. It's possible to do this with a list of post IDs and it will return the posts in the order specified, but in all those cases the order is already known before the query is executed.

Achieving what you desire with the main query will not be possible without executing multiple WP_Query beforehand, then extracting the results in PHP and compiling an array of post IDs and passing them to pre_get_posts. This will be unreliable and very slow.

The only feasible route I can foresee, is an integration via a plugin with software such as Elastic Search or Algolia.

1
  • 1
    I've marked this as the correct answer as it was both informative and gave me some direction to solving the problem. Many thanks.
    – MarkW
    Oct 14 '21 at 8:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.