Multi-value spatial search with Solr 4.x and Drupal 7

⚠️ Warning
This post is more than 10 years old. I do not delete posts, because even old information is still useful, but please know that some material on this page may be outdated or incorrect. Thanks!
Jul 11, 2014

For some time, Solr 3.x and Drupal 7 have been able to do geospatial search (using the location module, geofield, or other modules that stored latitude and longitude coordinates in Drupal that could be indexed by Apache Solr). Life was good—as long as you only had one location per node!

Sometimes, you may have a node (say a product, or a personality) affiliated with multiple locations. Perhaps you have a hammer that's available in three of your company's stores, or a speaker who is available to speak in two locations. When solr 3.x and Drupal 7 encountered this situation, you would either use a single location value in the index (so the second, third, etc. fields weren't indexed or searched), or if you put multiple values into solr's search index using the LatLonType, solr could throw out unexpected results (sometimes combining the closest latitude and closest longitude to a given point, meaning you get strange search results).

With Solr 4.x, especially Solr 4.3 and 4.5, there were some great improvements to spatial search, mostly enabled by switching from the old and trusty single-value LatLonType to the new (but slightly slower) SpatialRecursivePrefixTreeFieldType, or RPT for short.

Enabling this field type for the multi-value location field used by Apache Solr Search Integration and Search API involves an addition and a change in your schema.xml file. First, add the following after the "location" fieldType definition:

<fieldType name="location_rpt" class="solr.SpatialRecursivePrefixTreeFieldType"
           distErrPct="0.025"
           maxDistErr="0.000009"
           units="degrees" />

Then, find the locm_* dynamicField definition later in the file, and update it to use the new location_rpt fieldType we just defined:

<dynamicField name="locm_*" type="location_rpt" indexed="true"  stored="true" multiValued="true"/>

Once this is done, you will need to reindex your site (or at least all the content with location/geo fields). Once that's done, your search results can use a location filter (perhaps a user's entered or detected location), and that filter will apply to all the values attached to a particular node.

Some other advantages offered by the RPT field type (as opposed to the LatLonType) include:

  • Query by polygons and other complex shapes, in addition to circles & rectangles
  • Multi-valued indexed fields
  • Ability to index non-point shapes (e.g. polygons) as well as point shapes
  • Rectangles with user-specified corners that can cross the dateline
  • Multi-value distance sort and score boosting (warning: non-optimized)
  • Well-Known-Text (WKT) shape syntax (required for specifying polygons & other complex shapes)

Some of these features (not including the multi-value support) also require the addition of the property spatialContextFactory="com.spatial4j.core.context.jts.JtsSpatialContextFactory" to the fieldType definition in schema.xml as well as the installation of the JTS library to your Solr class path.

See more in the Apache Solr docs: SpatialRecursivePrefixTreeFieldType (abbreviated as RPT). Also, check out this issue proposing we add the above configuration (and updated documentation) to the shared configuration for Apache Solr/Search API: Spatial search improvements - new spatial fieldType on Solr 4.