Drupal 7: Geospatial Apache Solr searching in Drupal 7 using the Search API module (Ubuntu version, part 2)

This blog article in an update to a previous post Geospatial Apache Solr searching in Drupal 7 using the Search API module (Ubuntu version). In this article, I will outline a step by step guide on how to integrate Drupal 7 with the Search API modules to implement GeoSpatial searching in a View. I used a clean Ubuntu server (12.04 LTS) installation on a VirtualBox virtual machine.

Initial package installation

# update system packages
apt-get update
apt-get upgrade -y

# install ssh server
apt-get install openssh-server -y

# install apache + php
apt-get install php5 php5-cli php5-curl php5-common php5-gd php5-mysql php-pear -y

# install mysql server
apt-get install mysql-server -y

# install tomcat/java
apt-get install tomcat7 tomcat7-admin openjdk-7-jdk -y

# install git
apt-get install git

# install drush via pear
pear channel-discover pear.drush.org
pear install drush/drush
pear upgrade-all

Setting up MySQL

# add mysql db and user
mysql -p --execute="create database drupal7"
mysql -p --execute="GRANT ALL PRIVILEGES ON drupal7.* TO 'drupal7'@'localhost' IDENTIFIED BY 'lapurd'"

Creating the Apache vhost

# create directory
mkdir -p /var/www/vhosts/drupal7
cd /var/www/vhosts/drupal7

# download drupal via drush
drush dl drupal-7
mv drupal-7.15 html

# create a new git repo
git init
git add .
git commit -am "initial commit"

# install drupal via drush
cd html
drush site-install minimal --db-url=mysql://drupal7:lapurd@localhost/drupal7 --account-mail=drupal@ericlondon.com --account-pass=lapurd

Apache Configuration

# add apache vhost
# new file: /etc/apache2/sites-available/drupal7
<VirtualHost *:80>
    ServerAdmin webmaster@drupal7.dev

    ServerName drupal7.dev

    DocumentRoot /var/www/vhosts/drupal7/html
    <Directory /var/www/vhosts/drupal7/html>
        AllowOverride All
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/drupal7-error.log

    # Possible values include: debug, info, notice, warn, error, crit, alert, emerg.
    LogLevel warn

    CustomLog ${APACHE_LOG_DIR}/drupal7-access.log combined

</VirtualHost>

# enable apache vhost
cd /etc/apache2/sites-enabled
rm 000-default
ln -s ../sites-available/drupal7 000-drupal7

# enable apache mod_rewrite
a2enmod rewrite

# restart apache
apache2ctl restart

Drupal modules setup

cd /var/www/vhosts/drupal7/html

# core modules
drush en field_ui number options taxonomy list -y

# admin menu
drush dl admin_menu -y
drush en admin_menu -y

# views dependency
drush dl ctools -y
drush en ctools -y

# views
drush dl views -y
drush en views views_ui -y

# entity, search api dependency
drush dl entity -y
drush en entity -y

# facetapi, search api dependency
drush dl facetapi -y
drush en facetapi -y

# search api
drush dl search_api -y
drush en search_api search_api_views search_api_facetapi -y

# search_api_solr
mkdir sites/all/libraries
cd sites/all/libraries
wget http://solr-php-client.googlecode.com/files/SolrPhpClient.r60.2011-05-04.tgz
tar -xzf SolrPhpClient.r60.2011-05-04.tgz
cd ../../..
drush dl search_api_solr -y
drush en search_api_solr -y

# geofield module
drush dl geofield -y
drush en geofield -y

Tomcat & Solr setup

Edit file: /etc/tomcat7/tomcat-users.xml

+   <role rolename="admin"/>
+   <role rolename="manager"/>
+   <user username="eric" password="lapurd" roles="admin,manager"/>

- <!--
-   <role rolename="tomcat"/>
-   <role rolename="role1"/>
-   <user username="tomcat" password="tomcat" roles="tomcat"/>
-   <user username="both" password="tomcat" roles="tomcat,role1"/>
-   <user username="role1" password="tomcat" roles="role1"/>
- -->

Download Solr

# Download Solr & copy files
mkdir ~/downloads
cd ~/downloads
wget http://archive.apache.org/dist/lucene/solr/3.5.0/apache-solr-3.5.0.tgz
tar -xzf apache-solr-3.5.0.tgz
cp ~/downloads/apache-solr-3.5.0/dist/apache-solr-3.5.0.war /var/lib/tomcat7/webapps/solr.war
cp -r ~/downloads/apache-solr-3.5.0/example/solr/ /var/lib/tomcat7/solr/

New file: /etc/tomcat7/Catalina/localhost/solr.xml

<?xml version="1.0" encoding="UTF-8"?>
  <Context docBase="/var/lib/tomcat7/webapps/solr.war" debug="0" privileged="true" allowLinking="true" crossContext="true">
  <Environment name="solr/home" type="java.lang.String" value="/var/lib/tomcat7/solr" override="true" />
</Context>

Edit file: /var/lib/tomcat7/webapps/solr/WEB-INF/web.xml

- <env-entry-value>/put/your/solr/home/here</env-entry-value>

+ <env-entry-value>/var/lib/tomcat7/solr</env-entry-value>

Copy files and setup Tomcat

# copy files from search_api_solr module to tomcat directory
cp sites/all/modules/search_api_solr/schema.xml /var/lib/tomcat7/solr/conf/
cp sites/all/modules/search_api_solr/solrconfig.xml /var/lib/tomcat7/solr/conf/

# reset tomcat permissions
chown -R tomcat7.tomcat7 /var/lib/tomcat7/solr

# restart tomcat
service tomcat7 restart

# NOTE: admin interface URL
http://localhost:8080/solr/admin/

Drupal configuration


Add content type
- URL: /admin/structure/types/add
  - Name: Place (for example)
  - Save content type

Manage fields on new content type
- URL: /admin/structure/types/manage/place/fields
  - Add new field
    - Label: Geo
    - Machine name: field_geo
    - Field Type: Geofield
    - Widget: Latitude / Longitude
  - Save

Add Solr Server
- URL: /admin/config/search/search_api
- Add Server
  - Enter Server Name
  - Service class: choose Solr service
    - Enter Solr host (localhost), port (8080), path (/solr)
  - Save settings

Add solr index
- URL: /admin/config/search/search_api/add_index
  - Index name: GeoSolr
  - Item type: Node
  - Server: 
- Create index

Select fields to index
- URL: /admin/config/search/search_api/index/geosolr/fields
  - Add related fields
    - Choose "Geo", Add fields
    - Choose "The main body text", Add fields
  - Node ID, Integer
  - Title, Fulltext
  - Geo » LatLong Pair » String
  - The main body text » Text
- Save Changes

Added content
- URL: /node/add/place
  - Added coordinates manually using: http://gmaps-samples.googlecode.com/svn/trunk/geocoder/singlegeocode.html/

Index content
- URL: /admin/config/search/search_api/index/geosolr/status

NOTE: Execute direct Solr query to verify data and fields:
http://localhost:8080/solr/select/?q=&fl=*

Solr configuration changes per GeoSpatial

# changes to schema.xml:
root@ubuntu:/var/lib/tomcat7/solr/conf# diff schema.xml schema.xml.bak.orig
288,291d287
<     <fieldType name="point" class="solr.PointType" dimension="2" subFieldSuffix="_d"/>
<     <fieldType name="location" class="solr.LatLonType" subFieldSuffix="_coordinate"/>
<     <fieldtype name="geohash" class="solr.GeoHashField"/>
<
296,299d291
<
<    <field name="ss_field_geo:latlon" type="location" indexed="true" stored="true"/>
<    <dynamicField name="*_coordinate"  type="tdouble" indexed="true"  stored="false"/>
<

# restart tomcat
service tomcat7 restart

# direct solr query to verify geospatial results (using coordinates from Nashua, NH)
http://localhost:8080/solr/select/?q=&fl=*&fq={!geofilt%20sfield=ss_field_geo:latlon%20pt=42.933692,-72.278141%20d=100}

Add new Drupal view


- URL: /admin/structure/views/add
  - view name: GeoSearch
  - show GeoSolr sorted by Unsorted
  - Create a page
    - path: geosearch
  - save and continue
  - Format: Unformatted list
  - Show: Fields
    - Indexed Node: Node ID (Node ID)
    - Indexed Node: Geo (Geo)
    - Indexed Node: Title (Title)
    - The main body text: Text (indexed) (Text (indexed))
  - Save

Last I added a new module "geosearch" and added a hook_search_api_solr_query_alter() function to add the coordinates. It's up to you how you want to integrate the GeoSpatial integration with your Views and site.

<?php
function geosearch_search_api_solr_query_alter(array &$call_args, SearchApiQueryInterface $query) {

  $lat = 42.933692;
  $lng = -72.278141;
  $distance = 100;

  $call_args['params']['fq'][] = "{!geofilt sfield=ss_field_geo:latlon pt={$lat},{$lng} d={$distance}}";

}
?>