Software engineer, data guy, Open Source enthusiast, New Hampshire resident, husband, father. Fan of guitars, hiking, photography, homebrewing, sarcasm.
Drupal 7: Geospatial Apache Solr searching in Drupal 7 using the Search API module (Ubuntu version)
In this tutorial, I’ll share my notes and code I’ve used to setup geospatial Apache Solr searching in Drupal 7 using the Search API module. For this tutorial I created a minimal Ubuntu server virtual machine. All the commands should be executed as a user with permission to modify files, or prefixed with “sudo”.
The first thing I do with a fresh virtual machine is check for package upgrades.
I find it cumbersome to type in a virtual machine window, so I’ll install open-ssh and ssh from my Mac. If you plan to do so, you’ll need to find your virtual machine’s IP address using ifconfig. For this tutorial I added local DNS (/etc/hosts) to point “drupal7.vm” to my VM’s IP.
Install the LAMP stack. The following packages will install Apache httpd as a dependency.
At this point, browsing to your VM/server’s IP address will give you the standard Apache welcome message:
It works!
This is the default web page for this server.
The web server software is running but no content has been added, yet.
Install version control.
Create a mysql database for Drupal 7.
Install drush via Pear.
Verifying drush is installed.
Create an Apache vhost directory
Download drupal via drush
Integrate drupal file system with git
Install drupal via drush
Add Apache2 vhost
At this point browsing to your VM/server’s hostname should show a Drupal installation.
Part 2, Tomcat/Solr
Installing java jdk and tomcat6
Browsing to your VM/server’s hostname on port 8080 (ex: http://drupal7.vm:8080) will show the generic Tomcat welcome message:
It works !
If you’re seeing this page via a web browser, it means you’ve setup Tomcat successfully. Congratulations!
Installing Solr in Tomcat
Copy/rename java war file into Tomcat webapps directory
Note: copying the java war file into the Tomcat webapps folder will create this directory automatically: /var/lib/tomcat6/webapps/solr
Copy solr files
Create Catalina config file to link war file to solr directory
Setup Tomcat admin user(s)
Update webapps WEB-INF/web.xml file
Download search api drupal modules that contain solr xml configuration files, and copy into solr conf directory
Reset tomcat permissions, and restart tomcat
You should now be able to browse to the solr admin java page.
Example: http://drupal7.vm:8080/solr/admin/
If things aren’t working well at this point, check the Tomcat logs and look for SEVERE log entries, here: /var/log/tomcat6/catalina.out
In addition, the solr java module should be listed in the Tomcat Web Application Manager
Ex URL: http://drupal7.vm:8080/manager/html
Part 3, Drupal code
Getting the solr-php-client library from code.google.com
Downloading and installing contrib drupal modules
(Optionally) I install devel, admin_menu, and disable overlay/toolbar
Add the tomcat/solr server to Search API configuration:
You should receive some confirmation messages:
The server was successfully created.
The Solr server could be reached (latency: # ms).
If not, ensure tomcat/solr is reachable at the url you specified and the tomcat service is running.
At this point Solr is ready to send/receive data and index content, but there is nothing to index. For this tutorial, I decided to build off of user profiles and store latitude and longitude using the geolocation field module.
Adding some user profile fields:
I then added a bunch of users with latitude/longitude coordinates (URL: /admin/people/create). Note: I used Google Geocoding API to fetch the coordinates: http://code.google.com/apis/maps/documentation/geocoding/
Adding the search api index:
On the next admin page, you can select which fields to index. For this tutorial, I chose: User ID, Name, Email, URL, First Name, and Last Name. Unfortunately, at the time of writing this, the geolocation lat/lng fields are not exposed to the Entity API. I assume this is a temporary problem, and there are numerous patches in the geolocation issue queue.
@see (for example):
Property Info callback for Entity API - http://drupal.org/node/1366642
Fix for Search API not picking up the entity to index it’s fields - http://drupal.org/node/1320564
I copied code directly from the issues queue, made some modifications, and created a custom module to expose the geolocation field data to the entity api module. In addition, I added a new property “lat_lon” that concatenates lat and lng together with a comma. @see: http://wiki.apache.org/solr/SpatialSearch
I added this code to a custom module, renamed function calls (as necessary), and enabled. Update the solr index to add the new fields to the index:
The above will expose the following fields now available to the index:
Geolocation » Latitude
Geolocation » Longitude
Geolocation » Sine of Latitude
Geolocation » Cosine of Latitude
Geolocation » Radian Latitude
Geolocation » Latitude,Longitude
Enable “Geolocation » Latitude,Longitude” and save changes.
Index the content, URL: /admin/config/search/search_api/index/people/status. Click: Index now. Note: if you had already indexed the content, you’ll probably need to clear it first
In my environment, I got the following confirmation message:
Successfully indexed 7 items.
I find it to be very helpful to verify the xml response from Solr directly after making changes to the index/schema.
The following URL structure will query solr for all results and return all fields: Ex URL: http://drupal7.vm:8080/solr/select/?q=&fl=*
A sample XML document response.
Take note the field name in the following XML, it is used in the next file edit.
Update the solr schema.xml configuration and add the geospatial fieldType and field data.
Restart Tomcat
Since the schema and solr data types have been updated, the content will have to be re-indexed:
Returning to the solr query above will now show updated xml: (note: no longer an array)
Verify the native solr geospatial searching is working using the following query syntax:
URL: http://drupal7.vm:8080/solr/select/?q=&fl=*&fq={!geofilt sfield=t_field_geolocation:lat_lon pt=42.933692,-72.278141 d=100}
By putting a distance parameter of 100 (kilometers) and Nashua NH coordinates, I get 2 results: Nashua and Portsmouth, awesome.
Create a solr integrated view:
Note: at this point, you have full reign over view configuration. For this tutorial, I set the format to Grid, and added some fields:
Geolocation: Latitude,Longitude (indexed)
Indexed User: Email
Indexed User: First Name
Indexed User: Last Name
Indexed User: Name
Save the view when edits are complete.
Browsing to the view will show something like this:
Ex URL: http://drupal7.vm.people
The next chunk of custom code modifies the solr query executed and adds geospatial filtering.
@see: hook_search_api_solr_query_alter(array &$call_args, SearchApiQueryInterface $query)
The above code will limit the view’s results using the hardcoded coordinates.
Clearly it works but there are loose ends to tie:
automatically fetch a user’s coordinates to store in the geolocation field
add a search form to the people view page to allow the user to search for a location (instead of hard coded coordinates, blah)
translate the user’s location search input to coordinates using an API
Hopefully I can find more time to elaborate on this tutorial in the near future! Cheers.
User comments:
Created by Martin on 2012-08-10:
Great tutorial that helped me get on track with SOLR. About the hook for proximity filtering, you can instead set the option “spatial” on your search query like this: