David Cramer's Blog

How to Actually Make LocalSolr Work

Today I’ve been working on integrating geospatial search with our upcoming DISQUS Search product, which happens to rely on Solr. It didn’t take much work before I stumbled upon LocalSolr, which seems to be the defacto gis implementation. The docs were fairly brief, but it seemed easy to get up and running. It just so happens that it wasnt that easy after all. Hoping that this helps someone else out, here’s my step by step to getting it setup (locally, at least):

First up, you’re going to need to grab the localsolr libraries in some form or another. Hidden obscurely on a “Quick Start” link, is a tgz of an example project. It’s much like example project included with the actual Solr package, so it should be fairly straightforward. Once I had this, I pulled in my existing configuration to replace the example’s, and updating it per the docs.

The first set of changes needed to be made in solrconfig.xml. You’re going to need to add the localsolr component, and optionally the geofaceting component. You’ll also need to create a separate handler for geo searches (unless you plan to use longitude and latitude with every single search to Solr).

1
2
3
4
5
6
7
8
<searchComponent name="geofacet"
                 class="com.pjaol.search.solr.component.LocalSolrFacetComponent"/>

<searchComponent name="localsolr"
                 class="com.pjaol.search.solr.component.LocalSolrQueryComponent">
  <str name="latField">lat</str>
  <str name="lngField">lng</str>
</searchComponent>
1
2
3
4
5
6
7
<requestHandler name="geo" class="org.apache.solr.handler.component.SearchHandler">
  <arr name="components">
    <str>localsolr</str>
    <str>geofacet</str>
    <str>mlt</str>
  </arr>
</requestHandler>

Once done, you can move on to altering your schema.xml. It’s very important, that if you had used the examples on the LocalSolr site and already begun indexing, that you obliterate your index completely, as it will contain invalid data. This presents itself with an ugly, misleading (at least to Python folk) error: Invalid shift value in prefixCoded string. It turns out that you actually need to use tdouble instead of sdouble on all field types. Don’t ask me why, as I don’t care to know. So, on to the schema changes:

1
2
3
4
5
<!-- local lucene field types - ensure these are tdouble! -->
<field name="lat" type="tdouble" indexed="true" stored="false" required="false"/>
<field name="lng" type="tdouble" indexed="true" stored="false" required="false"/>
<field name="geo_distance" type="tdouble" required="false"/>
<dynamicField name="_local*" type="tdouble" indexed="true" stored="false"/>

Now just reindex your data and enjoy. You’ll need to pass the qt parameter when searching, and set it to geo (or whatever you named your requestHandler above).