Filter by one custom field, order by another?

I have a custom post type “Listing” and I want to get all Listings that have a custom field gateway_value != 'Yes', and order the results by another custom field, location_level1_value. I can get the queries to work separately, but I can’t combine them:

Query 1 (sort by location):

                $wp_query = new WP_Query( array (
                    'post_type' => 'listing',
                    'post_status' => 'publish',
                    'posts_per_page' => '9',
                    'meta_key' => 'location_level1_value',
                    'orderby' => 'location_level1_value',
                    'order' => 'ASC',
                    'paged' => $paged
                    )
                 );

Query 2 (custom field value != Yes):

                $wp_query = new WP_Query( array (
                    'post_type' => 'listing',
                    'posts_per_page' => '9',
                    'post_status' => 'publish',
                    'meta_key' => 'gateway_value',
                    'meta_value' => 'Yes',
                    'meta_compare' => '!=',
                    'paged' => $paged
                    )
                );

Combined query:

I looked at the codex for help with this, but the following query does not work:

Read More
                $wp_query = new WP_Query( array (
                    'post_type' => 'listing',
                    'posts_per_page' => '9',
                    'post_status' => 'publish',
                    'meta_query' => array(
                        array(
                            'key' => 'gateway_value',
                            'value' => 'Yes',
                            'compare' => '!='
                        ),
                        array(
                            'key' => 'location_level1_value'
                        )
                    ),
                    'orderby' => "location_level1_value",
                    'order' => 'ASC',
                    'paged' => $paged
                    )
                );

What am I doing wrong with the combined query?

[UPDATE]: So now that 3.1 has been released, the combined query above still does not work. I do get results, just not sorted correctly.

[UPDATE]: var_dump($wp_query->request) gives the following:
string(527) " SELECT SQL_CALC_FOUND_ROWS wp_7v1oev_posts.* FROM wp_7v1oev_posts
INNER JOIN wp_7v1oev_postmeta ON (wp_7v1oev_posts.ID = wp_7v1oev_postmeta.post_id)
INNER JOIN wp_7v1oev_postmeta AS mt1 ON (wp_7v1oev_posts.ID = mt1.post_id) WHERE 1=1 AND wp_7v1oev_posts.post_type = 'listing' AND (wp_7v1oev_posts.post_status = 'publish') AND wp_7v1oev_postmeta.meta_key = 'gateway_value' AND CAST(wp_7v1oev_postmeta.meta_value AS CHAR) != 'Yes' AND mt1.meta_key = 'location_level1_value' ORDER BY wp_7v1oev_posts.post_date DESC LIMIT 0, 9"

Related posts

Leave a Reply

3 comments

  1. You could use the query to filter the content as you intended by using the ‘meta_query’ with filtering options, and for the order part, just add/modify the following parameters:

    • ‘orderby’ => ‘meta_value’
    • ‘meta_key’ => ‘location_level1_value’
    • ‘order’ => ‘ASC’

      $wp_query = new WP_Query( array (
          'post_type'      => 'listing',
          'posts_per_page' => '9',
          'post_status'    => 'publish',
          'meta_query'     => array(
              array(
                  'key'       => 'gateway_value',
                  'value'     => 'Yes',
                  'compare'   => '!='
              )
          ),
          'orderby'  => 'meta_value',            // this means we will be using a selected 
                                                 // meta field to order
      
          'meta_key' => 'location_level1_value', // this states which meta field 
                                                 // will be used in the ordering, 
                                                 // regardless of the filters
          'order'    => 'ASC',
          'paged'    => $paged
          )
      );
      
  2. Just like Jan said in new WordPress 3.1 you can use meta_query but until that will come out you can use your First query to orderby and filter inside your loop like so:

     Global $my_query;
    $my_query = new WP_Query( array (
                        'post_type' => 'listing',
                        'post_status' => 'publish',
                        'posts_per_page' => '9',
                        'meta_key' => 'location_level1_value',
                        'orderby' => 'location_level1_value',
                        'order' => 'ASC',
                        'paged' => $paged
                        )
                     );
    while ($my_query->have_posts){
        $my_query->the_post();
                  //do your loop stuff
    } 
    

    and add this code to your functions.php

       //join filter
             add_filter('posts_join', 'listing_join_865' );
             function listing_join_865($join){
    Global$ my_query;            
    if ('listing' = $my_query->query['post_type']){
                    $restriction1 = 'gateway_value';
                    return $join .="
                    LEFT JOIN $wpdb->postmeta AS $restriction1 ON(
                    $wpdb->posts.ID = $restriction1.post_id
                    AND $restriction1.meta_key = '$restriction1'
                    )";
                 }else {
                    return $join;
                }
             }
             //where filter
             add_filter('posts_where', 'listing_where_865' );
             function listing_where_865($where){
                 global $my_query;
                if ('listing' = $my_query->query['post_type']){
                    return $where.= " AND $restriction1.meta_value != 'yes'";
                }else{
                    return $where;
                }
             }
    

    now this should work.

  3. Apologies for answering my own question:

    Looking at [http://core.trac.wordpress.org/ticket/15031][1], seems like this is a known issue. I have fixed (hacked?) it to work using post_filter, like so (just for anyone’s reference who might be searching for the same answer):

    In functions.php###

    add_filter('posts_orderby', 'EV_locationl1' );
    function EV_locationl1 ($orderby) {
        global $EV_locationl1_orderby;
        if ($EV_locationl1_orderby) $orderby = $EV_locationl1_orderby;
        return $orderby;
    }
    

    Amended wp_query in template file###

    $EV_locationl1_orderby = " mt1.meta_value ASC";
    
    $wp_query = new WP_Query( array (
        'post_type' => 'listing',
        'posts_per_page' => '9',
        'post_status' => 'publish',
        'meta_query' => array(
                array(
                        'key' => 'gateway_value',
                        'value' => 'Yes',
                        'compare' => '!='
                        ),
                array(
                        'key' => 'location_level1_value'
                )
            ),
        'order' => $EV_locationl1_orderby,
        'paged' => $paged
        ));