Howto: zip code proximity search using Location Module

Last modified: September 19, 2009 - 00:02

Note: This issue might lead to more information on the "right" way to do location views.
http://drupal.org/node/430730

Note: There is currently a bug in Location module that causes searches greater than 3285 miles or 5288 kilometers to return no results. Be warned and test within that limit. Update: I've got a theme-based workaround for this problem that makes things at least not break: http://drupal.org/node/471040 comment #3.

I have fully updated and tested this tutorial and added screenshots in response to comments. This is a tutorial on how to use the Location module to search by zip code proximity in Drupal 6.

This view will ultimately accept an inputted user zip code and return a listing of content sorted by distance from that zip code.

The first draft of this tutorial created a view that worked for me for a while but mysteriously quit working. I honestly had two identical views, one of which worked, one of which did not. I re-did it from scratch and took screenshots. I suggest following this tutorial exactly if possible and then modifying it to suit your needs. There seems to be a narrow path. ;^)

First, you must install the Location and Views modules and configure Location fields for whatever content type you desire.

Note:The actual Location fields I am using are not CCK Location fields, but are Node Location fields, that is, Locations attached to the nodes themselves (which one adds to the nodes via CCK) rather than locations attached to a CCK field on that node. Some of the confusions below may have arisen from this difference.

(Note: I also recommend Gmap module, though I won't be using it in this tutorial. The Gmap module essentially provides Views with another way to display data, in place of a listing of fields. You could use the Gmap module to display the described view below by selecting "Style: Gmap" in place of "Style" Field". But I'd first get it working the way below to remove variables.)

Next, upload the zip codes from the country of your choice as per the INSTALL.TXT file found in the Location module. The zip code database tables are located (usually) at /sites/all/modules/location/database/. You can simply open the file of your choice with a text editor, copy all, and paste into a PHPmyAmin SQL execute window. If it's too big, paste it in several batches. This creates a whole list of zip codes to search from.

Create a new view:

  1. new view
  2. type: Location
  3. Select Style: Field
  4. Configure the fields your view will display. It seems that you must choose distance/proximity to be displayed or this view will not work consistently. I recommend also selecting the "Location:Address" field as well as the "Title", for testing purposes.

  5. Configure the Filters that will be used to limit the locations returned by the query. We will set up a filter that will return only locations that are within a set range of an user-inputted zip code.
  6. Location: Distance / Proximity

    Expose the filter

    select Form Mode -> Postal Code (with country default)

    The following settings are optional:
    * Node Type: [node type with locations attached]
    * Node: Published [always check this!]

  7. Sort Criteria
  8. Note: If your sorting doesn't work, delete the sort criterion and re-add it. Others have confirmed this.
    Choose Location: Distance / Proximity (you know the drill by now!)
    On extra settings: select use Distance / Proximity filter (this hooks the sort criteria up to the filter that collected the user's entered zip code)

  9. Shot of the whole view, in case I missed anything. Remember to add a page view or block view or your view will not be displayed anyplace.

Another way to import to SQL database

Use a command like the following to import the ZIP code database.
Note that this is on a Mac (*nix).

mysql -u usernamehere --password=passwordhere -h localhost -D databasenamehere < zipcodes.us.mysql

My gui locked up after about 5 minutes. The command above took under 5 seconds :) Amazing!

AttachmentSize
distance-proximity-filter.png25.82 KB
distance-proximity-filter-2.png37.32 KB
distance-proximity-filter-exposed.png54.3 KB
distance-proximity-filter-extra-settings.png32.62 KB
distance-proximity-sort.png44.22 KB
distance-proximity-sort.png44.22 KB
view-type.png30.77 KB
distance-proximity-field.png32.38 KB
whole-view.png114.32 KB

Not Working

saurabh.bhambry - August 10, 2009 - 00:39

I tried to repeat this 3 times without much success. The search doesn't throw any results. I did ensure the following as cautioned int the tute above:

1) Location data is the one collected through the Node Locations and not the one collected through CCK Location Field.

2) I did install the zip codes of US. I specifically ran the queries related to zip codes of Naples, FL only.

Even in the preview clicking Apply gets no results. However in the Distance if I Type 0 and den click apply den all locations unfiltered are listed. I have kept both the filters viz. Postal Code and Distance Optional still leaving them blank and clicking Apply doesnt give any results.

Also, I had tried to add the display as Block but the same wouldn't show.

Kindly help me understand where am I going wrong.

Bhambry

trying swapping lattitude and longitude column before importing

juicytoo - August 13, 2009 - 15:02

Hi,

I think this page has changed and some of the previous comments by posters have been deleted.

I use the au.txt sql dump from geonames, and I remember that someone ( I forgot who ) advised me to swap the latitude and longitude columns of the au.txt table before importing.

That fixed my problem.

ie.
the coordinate table got reversed.

cheers

cheers
Ed
geeksupport.com.au

Two things helped me to get

OzSchmoz - August 14, 2009 - 10:23

Two things helped me to get this working. The first was this:

http://drupal.org/node/338929#comment-1248874

And the second was realising that you can only enter the first part of the postcode - e.g. S10. If you enter the second, the query produces no results.

Hope that helps.

I'm getting the same problem

OzSchmoz - August 11, 2009 - 16:32

I'm getting the same problem as above.

If I type 0 into distance, I get a list of all the nodes but for each one the "Distance / Proximity:" field gives no value.

I have checked all the settings carefully and am using the latest versions of all modules.

Ditto

PlasmaFlux - September 7, 2009 - 06:44

OzSchmoz,

I'm having the same results. Did you ever get this sorted out?

Thanks.

You could do something like this

glass.dimly - September 7, 2009 - 19:07

<?php if ($GLOBALS['HTTP_GET_VARS']['distance']['search_distance'] < 1 ) {
   
$GLOBALS['HTTP_GET_VARS']['distance']['search_distance'] = 1;
    }
 
?>

Which would change any search for zero into one. This is not tested, however the code that I link to below is.

This can be used like the code located here: http://drupal.org/node/471040 comment 3.

Working

karlazz - October 29, 2009 - 18:51

I made this work, courtesy of someone else's post, since I didn't have a clue about how Drupal works, let alone views, gmap, and location nodes. When I get to my other computer, I will find the helpful link and add it to this thread. And I will thank the nice lady for posting it.

Here's my next problem though: zip codes are nice and all, but what I want to do is allow my users to search using City, Street, or Cross Street. Essentially, I want this to work anywhere in the world, and to be helpful when a person only knows either where they are currently, or what city they want to look at. Zip codes are kind of specialized. Let's not get into problems related to alternate alphabets and other languages. Let's assume Latin Alphabet, English Language for now.

Anyone done this? Like I said, I am new to Drupal.

Thanks

Can't get it to work

alioso_oopa - November 7, 2009 - 20:21

I have tried various solutions proposed in http://drupal.org/node/321114.
I am trying to set up a user search by postal code for US and I am hitting the wall. I am using the user location mod provided by Location.
Zipcodes have been properly imported in my database. I tried several patches, tried to reverse latitude and longitude in the database, but didn't get any result.
Mostly my query returns all users without any lat and long in the table, and returns nothing if I enter the full zip.
If i enter 4, 3 2 or 1 of the digits of the zip then it returns all results despite the distance input (100 miles for instance).
This doesn't make much sense to me and there must be something I am doing wrong. I followed this tutorial to set up the views obviously, but tried to set up other views on my own without any luck.
I was wondering if anybody has a solution. @karlazz, you mentioned making this work with the help of another post. Would you mind sharing this?
Thanks.

I've done exacly the same as

Remco - November 17, 2009 - 15:04

I've done exacly the same as you discribed here and i cant get it working eather.... Even made a forum topic bout it: http://drupal.org/node/628558

Nothing found yet....

//edit.. Got it working.

There was once a huge number...

glass.dimly - November 7, 2009 - 21:10

...of helpful comments on this doc page, but someone deleted them all.

Would it be possible to also

Remco - November 17, 2009 - 15:12

Would it be possible to also display the filtered results right under the map?

"WHERE 0" problem with SQL produced

tolland76 - November 20, 2009 - 01:58

The SQL that is produced by my view with a distance/proximity filter always has a "WHERE 0" on the end, which is always returning no results. Any ideas what I am doing wrong, I have dumped my view export in below;

"SELECT location.lid AS lid,
node.title AS node_title,
node.nid AS node_nid
FROM location location
LEFT JOIN location_instance location_instance ON location.lid = location_instance.lid
LEFT JOIN node node ON location_instance.vid = node.vid
WHERE 0
"

$view = new view;
$view->name = 'mapsviewprops';
$view->description = 'mapsviewprops';
$view->tag = 'mapsviewprops';
$view->view_php = '';
$view->base_table = 'location';
$view->is_cacheable = FALSE;
$view->api_version = 2;
$view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */
$handler = $view->new_display('default', 'Defaults', 'default');
$handler->override_option('fields', array(
'address' => array(
'label' => 'Address',
'alter' => array(
'alter_text' => 0,
'text' => '',
'make_link' => 0,
'path' => '',
'link_class' => '',
'alt' => '',
'prefix' => '',
'suffix' => '',
'target' => '',
'help' => '',
'trim' => 0,
'max_length' => '',
'word_boundary' => 1,
'ellipsis' => 1,
'strip_tags' => 0,
'html' => 0,
),
'empty' => '',
'hide_empty' => 0,
'empty_zero' => 0,
'hide' => array(
'name' => 0,
'street' => 0,
'additional' => 0,
'city' => 0,
'province' => 0,
'postal_code' => 0,
'country' => 0,
'locpick' => 0,
'phone' => 0,
'province_name' => 0,
'country_name' => 0,
'map_link' => 0,
'coords' => 0,
),
'exclude' => 0,
'id' => 'address',
'table' => 'location',
'field' => 'address',
'override' => array(
'button' => 'Override',
),
'relationship' => 'none',
),
'title' => array(
'label' => 'Title',
'alter' => array(
'alter_text' => 0,
'text' => '',
'make_link' => 0,
'path' => '',
'link_class' => '',
'alt' => '',
'prefix' => '',
'suffix' => '',
'target' => '',
'help' => '',
'trim' => 0,
'max_length' => '',
'word_boundary' => 1,
'ellipsis' => 1,
'strip_tags' => 0,
'html' => 0,
),
'empty' => '',
'hide_empty' => 0,
'empty_zero' => 0,
'link_to_node' => 1,
'exclude' => 0,
'id' => 'title',
'table' => 'node',
'field' => 'title',
'override' => array(
'button' => 'Override',
),
'relationship' => 'none',
),
));
$handler->override_option('filters', array(
'distance' => array(
'operator' => 'dist',
'value' => array(
'latitude' => '',
'longitude' => '',
'postal_code' => '',
'country' => '',
'search_distance' => '100',
'search_units' => 'mile',
),
'group' => '0',
'exposed' => TRUE,
'expose' => array(
'use_operator' => 0,
'operator' => 'distance_op',
'identifier' => 'distance',
'label' => 'Location: Distance / Proximity',
'optional' => 1,
'remember' => 0,
),
'type' => 'postal_default',
'identifier' => 'dist',
'id' => 'distance',
'table' => 'location',
'field' => 'distance',
'relationship' => 'none',
),
));
$handler->override_option('access', array(
'type' => 'none',
));
$handler->override_option('cache', array(
'type' => 'none',
));
$handler = $view->new_display('page', 'Page', 'page_1');
$handler->override_option('path', 'maps1111');
$handler->override_option('menu', array(
'type' => 'none',
'title' => '',
'description' => '',
'weight' => 0,
'name' => 'navigation',
));
$handler->override_option('tab_options', array(
'type' => 'none',
'title' => '',
'description' => '',
'weight' => 0,
));

ah, this has come up before.

tolland76 - November 20, 2009 - 03:47

ah, this has come up before. I am in the uk and I patched it with the file attached to this comment;
http://drupal.org/node/321114#comment-1507534

and it worked good!

Batch importing locations

mediatoaster - November 23, 2009 - 16:03

I got the zipcode search working properly when I manually add locations however I'm having issues getting the search to see locations I've added through a batch import to the DB.

The batch imported successfully. I set source=4 in the location table and all locations appear under the search box before I attempt to narrow down the results by the proximity search.

I've found the search only works for a location after I manually follow the link to the Google Maps results for each individual location so it can catalog the actual longitude/latitude data into the database.

Is there any fix or workaround for this or am I missing something? I can't manually click each link for the 5000+ locations I have to import. It kind of defeats the purpose of a batch.

 
 

Drupal is a registered trademark of Dries Buytaert.