Yelp/yelp-python

search_by_coordinates only returns food results

Closed this issue · 10 comments

I have been trying to use search_by_coordinates to find POI around me but it seems that it only returns the same food results no matter what I put in as term. See below

Inputs:

params = {
'term': 'superstore',
'limit': '40',
'radius_filter': '10000'
}
response = client.search_by_coordinates( lat, lng, params )

url generated under sign_request

https://api.yelp.com/v2/search/?ll=51.0454027%2C-114.0565189%2C%7B%27term%27%3A+%27superstore%27%2C+%27limit%27%3A+%2740%27%2C+%27radius_filter%27%3A+%2710000%27%7D&oauth_token=XXXXXXXXXXXXXXXXX&oauth_consumer_key=XXXXXXXXXXXXXXXXXX&oauth_nonce=84599947&oauth_timestamp=1457744867

i'm not sure if term=superstore should go right after search/? and this is not happening here. I'm wondering if API is treating it as empty search term.

image

parameters are passed wrong in here.

Alright, it turns out you need to do it this way
image

But this won't work. Guess what, lat and lng needs to be at end of url!!!!

So you get something like this
image

and the API complains about InvalidParameter

But if you get rid of limit and radius_filter and leaving only term
image

you can get a url with 'll' at the end
image

and the API will give you some good results....

image

So when we generate the url. maybe find a way to leave lat and lng terms at the end?

Hm, I know some OAuth libraries want query-string args to be in alphabetical order, I wonder if that's what we're hitting here.

ya i think so... looks like it's in reverse alphabetical order. "term", "ll", "limit"

Digging in, trying to reproduce locally.

@FiniteElementries : What version of the oauth2 library are you using? pip freeze | grep oauth will get the answer I'm looking for.

Hi @mittonk , oauth2==1.9.0.post1 is what I have got. Thanks for looking into this. Cheers~

OK, reproduced problem.

1. One layer of the onion: in your first attempt,

response = client.search_by_coordinates( lat, lng, params )

the params dict is getting passed in as the accuracy argument, and leaving term, limit, and radius_filter empty. Using the Python **kwargs feature (https://docs.python.org/2/tutorial/controlflow.html#keyword-arguments) gets us further:

response = client.search_by_coordinates(lat, lng, **params)

That's basically equivalent to

response = client.search_by_coordinates(lat, lng, term='superstore', limit=40, radius_filter=10000)

That gets us to a fairly unhelpful

InvalidParameter:

error.

(You were seeing food results like Thi Thi Vietnamese Subs because term='' just gives very-popular businesses, and the most popular businesses near you happen to be food.)

2. Next layer of the onion: Adding some ipdb.set_trace() diagnostics to the error-printing code, I find the actual error from the API is:

ipdb> response
{u'error': {u'field': u'limit', u'text': u'One or more parameters are invalid in request', u'description': u'Limit maximum is 20', u'id': u'INVALID_PARAMETER'}}

That's much clearer. (The clientlib should print that whole error, would have saved us a bunch of time: issue #44).

3. Dropping limit to 20 as allowed by the API gives our expected result:

response = client.search_by_coordinates(lat, lng, term='superstore', limit=20, radius_filter=10000)
print response.businesses[0].name                                               
Real Canadian Superstore

(You could also use search_by_coordinates(lat, lng, **params) but I think this form is clearer).

So, there's nothing about alphabetical order (sorry for the false alarm), just Python keyword ordering, an illegal input, and a woefully inadequate error message.

@FiniteElementries : Is that enough to get you rolling again?

Thanks for the nice adventure, we'll work on improving the error messages!

@mittonk lol that's a tricky one. Thanks man. It works!

Awesome.