1

I have places stored as posts in WP's posts table.

I am doing some geo-locating using Geo Data Store (http://wordpress.org/plugins/geo-data-store/). This is working great for me, as I can currently get results from any radius I choose from a starting point (a city converted to coordinates).

I was previously using an exact match on the city - when a user clicked a city, it loaded results with posts that held postmeta exactly matching the clicked city - I click Asheville, I get places in Asheville.

The problem that switching to geo-location has caused is that now when a user clicks a city, some results within that city aren't shown because they are not within the given radius of the city center, even though the city postmeta exactly matches the clicked city.

The relevant part of my query looks like this:

$coordinates = ConvertCityStateToCoords($city.', '.$state);
$lat = (double)$coordinates['lat'];
$long = (double)$coordinates['long'];
$posts = (array) $geoDataStore->getPostIDsOfInRange('place', $radius, $lat, $long);
$posts = array_map('intval',$posts);
$args['post__in']=$posts;
$places= new WP_Query($args);

Whereas it used to look like this:

$args['meta_query'][] = array(
    'key' => 'place_state',
    'value' => $state,
);
$args['meta_query'][] = array(
    'key' => 'place_city',
    'value' => $city
);
$places= new WP_Query( $args );

My question is this: will I have to abandon WP_Query (which I would rather not do because I am also using it for pagination and ordering) in favor of SQL that will allow me to query an 'optional' field - SQL that would include posts within the radius as well as posts with the exact match city, but not exclusively one or the other.

2 Answers 2

1

All of the real work here is being done by $geoDataStore->getPostIDsOfInRange. That is where the search is done and that is what isn't returning the results you want.

WP_Query just pulls the specified post IDs. There is no reason you should have to abandon that part of the code, though you may want to add 'orderby' => 'posts__in' to preserve the order of the post IDs passed into the query.

If $geoDataStore->getPostIDsOfInRange is not returning all of the IDs you want, you will have to look into how it works.

Now, this looks like the code that your $geoDataStore class uses to make the query. There are no hooks in that you might be able to manipulate.

There are only two things I can think of doing.

  1. Extend that class and replace that function so that it searches your meta information.
  2. Or run another query to check your meta information and include the places outside the generated radius-- something like this.

In other words...

$posts = (array) $geoDataStore->getPostIDsOfInRange('place', $radius, $lat, $long);
$posts2 = new WP_Query(array(
  // query for the others
  'fields' => 'ids',
  // other parameters
  // Much like your original meta_query but
  // I do think you need the 'OR' relationship
));
$posts = array_unique($posts + $posts2);
$args['post__in'] = $posts;
$places = new WP_Query($args);
4
  • Please re-read my question. The query that you modified was my OLD query. The query I am currently working on is listed as such. In addition, my old query had no need to query with an 'OR' parameter between city and state. Commented May 31, 2013 at 20:01
  • @JoshLevinson : My apologies. You are right.
    – s_ha_dum
    Commented May 31, 2013 at 20:05
  • No problem :) I was thinking of a similar to solution to your latest edit, but was getting hung up on pagination as I was joining two WP_Querys after they had been created. Getting the results separately and then using the generated ids for a new query with the Args including pagination should work, though it is unfortunate that three separate database runs must be done for this method. Thanks for your insight - I'll post back with my results! Commented Jun 2, 2013 at 0:43
  • Forgot to come back and update! I ended up using your methods here; thanks for your input! Commented Jul 26, 2013 at 16:25
0

You need to declare an OR relationship between the queries, as AND is default.

Example taken from http://codex.wordpress.org/Class_Reference/WP_Query#Custom_Field_Parameters

$args = array(
    'post_type' => 'product',
    'meta_query' => array(
        'relation' => 'OR',
        array(
            'key' => 'color',
            'value' => 'blue',
            'compare' => 'NOT LIKE'
        ),
        array(
            'key' => 'price',
            'value' => array( 20, 100 ),
            'type' => 'numeric',
            'compare' => 'BETWEEN'
        )
    )
);
2
  • Wouldn't this only apply if I was using meta_query for the filtering? Please refer to my question - metaquery is how my OLD method worked, before geolocation. Now the latitude and longitude are in a completely separate table. Commented Jun 1, 2013 at 1:56
  • Ah, I reckon you're right. But then it's hard to imagine wp_query working on non WP tables, at least for me.
    – GhostToast
    Commented Jun 1, 2013 at 5:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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