<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>joelmats</title>
	<atom:link href="http://joelmats.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://joelmats.wordpress.com</link>
	<description>Just another WordPress.com site</description>
	<lastBuildDate>Sun, 04 Mar 2012 04:35:11 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='joelmats.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>joelmats</title>
		<link>http://joelmats.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://joelmats.wordpress.com/osd.xml" title="joelmats" />
	<atom:link rel='hub' href='http://joelmats.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Sunspot 1.2 with Spatial Solr Plugin 2.0</title>
		<link>http://joelmats.wordpress.com/2011/02/23/getting-sunspot-1-2-with-spatial-solr-plugin-2-0-to-work/</link>
		<comments>http://joelmats.wordpress.com/2011/02/23/getting-sunspot-1-2-with-spatial-solr-plugin-2-0-to-work/#comments</comments>
		<pubDate>Wed, 23 Feb 2011 21:55:41 +0000</pubDate>
		<dc:creator>joelmats</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[rails-3]]></category>
		<category><![CDATA[solr]]></category>
		<category><![CDATA[sunspot]]></category>

		<guid isPermaLink="false">http://joelmats.wordpress.com/?p=9</guid>
		<description><![CDATA[Currently I am porting an application from Rails 2.x to 3.x. The old version uses a plugin called acts_as_solr but is no longer actively maintained and has been stale for a while. Fortunately I found Sunspot, an elegant and clean solution to &#8230; <a href="http://joelmats.wordpress.com/2011/02/23/getting-sunspot-1-2-with-spatial-solr-plugin-2-0-to-work/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=joelmats.wordpress.com&#038;blog=20399518&#038;post=9&#038;subd=joelmats&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Currently I am porting an <a href="http://www.clinicbook.com" title="clinicbook">application</a> from Rails 2.x to 3.x. The old version uses a plugin called acts_as_solr but is no longer actively maintained and has been stale for a while. Fortunately I found <a title="Sunspot Solr Github" href="https://github.com/outoftime/sunspot">Sunspot</a>, an elegant and clean solution to adding SOLR to Rails applications.</p>
<p>For geo-location based searches, Sunpot uses a really cool technique called <a href="http://blog.websolr.com/post/1336392145/spatial-search-in-sunspot">Geohashing</a> as Apache Solr does not provide built in support for location searches (a feature expected in the 4.0 <a title="Solr 4.0 Spatial Search" href="http://wiki.apache.org/solr/SpatialSearch">release</a>). However, in my case, I needed the ability to bound searches with finer granularity then the 10 or so precision bounds provided by geohashing. I opted to use <a title="Spatial Solr Plugin 2.0" href="http://blog.jteam.nl/2010/12/22/ssp-2-0/">Spatial Solr Plugin</a> to provide the spatial component for search.</p>
<p>1. Download SSP and add the jar file to your Solr lib directory. Sunspot should have created this directory in your project root project_root/solr/lib.</p>
<p>2. Modify Rails.root/solr/conf/solrconfig.xml and add the following</p>
<pre class="brush: xml; title: ; notranslate">
...
&lt;!-- Configuration for using Spatial Solr Plugin (SSP) 2.0 --&gt;
&lt;queryParser name=&quot;spatial&quot; class=&quot;nl.jteam.search.solrext.spatial.SpatialQParserPlugin&quot;&gt;
  &lt;str name=&quot;latField&quot;&gt;lat&lt;/str&gt;
  &lt;str name=&quot;lngField&quot;&gt;lng&lt;/str&gt;
&lt;/queryParser&gt;
 
&lt;searchComponent name=&quot;geoDistance&quot; class=&quot;nl.jteam.search.solrext.spatial.GeoDistanceComponent&quot;/&gt;

&lt;requestHandler name=&quot;standard&quot; class=&quot;solr.SearchHandler&quot; default=&quot;true&quot;&gt;
  &lt;!-- default values for query parameters --&gt;
  &lt;lst name=&quot;defaults&quot;&gt;
    &lt;str name=&quot;echoParams&quot;&gt;explicit&lt;/str&gt;
    &lt;str name=&quot;distanceField&quot;&gt;distance&lt;/str&gt;
  &lt;/lst&gt;
  &lt;arr name=&quot;last-components&quot;&gt;
    &lt;str&gt;geoDistance&lt;/str&gt;
  &lt;/arr&gt;
&lt;/requestHandler&gt;
...
</pre>
<p><strong>Note:</strong> The requestHandler with the name attribute as &#8220;standard&#8221; already exists so you just need to add the new fields to your current definition.</p>
<p>The two fields &#8220;latField&#8221; and &#8220;lngField&#8221; in the queryParser element defines the field name that SSP will use for its spatial search. For simplicity, I used the default names lat and lng.</p>
<p>3. Modify project_root/solr/conf/schema.xml and add the field definitions for lat and lng. In Sunspot&#8217;s configuration, it seems to already come with a lat and lng field that isn&#8217;t being used anymore so I decided to reuse them and just modified the type attribute to &#8220;tdouble&#8221;, a Trie Double.</p>
<pre class="brush: xml; title: ; notranslate">
...
&lt;!-- *** This field is used by Sunspot! *** --&gt;
&lt;field name=&quot;lat&quot; stored=&quot;true&quot; type=&quot;tdouble&quot; multiValued=&quot;false&quot; indexed=&quot;true&quot;/&gt;
&lt;!-- *** This field is used by Sunspot! *** --&gt;
&lt;field name=&quot;lng&quot; stored=&quot;true&quot; type=&quot;tdouble&quot; multiValued=&quot;false&quot; indexed=&quot;true&quot;/&gt;
...
</pre>
<p>4. In your ActiveRecord model, modify your searchable block to add indexing for lat and lng. For example, if your model attributes were latitude and longitude&#8230;</p>
<pre class="brush: ruby; title: ; notranslate">
searchable do
...
  double :latitude, :as =&gt; &quot;lat&quot;
  double :longitude, :as =&gt; &quot;lng&quot;
...
end
</pre>
<p>5. Restart Solr server and reindex using<br />
<code><br />
rake sunspot:solr:stop<br />
rake sunspot:solr:start<br />
rake sunspot:solr:reindex<br />
</code><br />
If you browse to your solr schema browser (default: 127.0.0.1:8982/admin/solr/schema.jsp), you should see the lat and lng fields are indexed.</p>
<p>6. Next we need to add support to get the &#8220;distance&#8221; field from the results. To do this, I added the following into a file in project_root/conf/initializers</p>
<pre class="brush: ruby; title: ; notranslate">
module Sunspot
  
  class Search::Hit
    def distance
      @stored_values['distance'] # distance_field_name
    end
  end
  
  class Query::Sort::DistanceSort &lt; Query::Sort::Abstract
    def to_param
      &quot;distance #{direction_for_solr}&quot; # distance_field_name
    end
  end
  
end
</pre>
<p><strong>Edit:</strong> Sunspot requires that a valid class name be defined for sorting on fields that are not explicitly defined in the searchable clause. I&#8217;ve added an additional class into the module Sunspot::Query::Sort. Koodos to Craig for pointing this out.</p>
<p>This defines a new method in the Hit object that returns the field &#8216;distance&#8217; from the solr results. If you named the distanceField in solrconfig.xml differently, you will need to modify this accordingly.</p>
<p>7. Now you can define a search using the adjust_solr_params. Use the order_by with :distance to sort on the distance.</p>
<pre class="brush: ruby; title: ; notranslate">
@results = Model.search do
...
  order_by(:distance, :desc) # Order by distance from farthest to closest

  adjust_solr_params do |params|
    params[:q] = &quot;{!spatial qtype=dismax boost=#{some_boost_val} circles=#{search_lat},#{search_lng},#{search_radius}}&quot; + &quot;#{params[:q]}&quot;
  end
end
</pre>
<p>The adjust_solr_params adjusts the solr query parameter right before its sent off to solr. We prepend the spatial search syntax to the beginning and leave the built query intact. That way, we can still make use of the other DSL defined search parameters. Since Sunspot uses dismax by default, i&#8217;ve set the qtype parameter so that the text portion of the search is passed to the dismax parser.</p>
<p>8. Access the distance field like</p>
<pre class="brush: ruby; title: ; notranslate">
@results.hits do |hit, result|
  puts hit.distance
end
</pre>
<p><strong>Note:</strong> I haven&#8217;t tested this with complex queries using faceting but I think it should work. The only thing is that I&#8217;m not sure what will happen if you use this alongside geohashing, not that you would need to.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/joelmats.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/joelmats.wordpress.com/9/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=joelmats.wordpress.com&#038;blog=20399518&#038;post=9&#038;subd=joelmats&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://joelmats.wordpress.com/2011/02/23/getting-sunspot-1-2-with-spatial-solr-plugin-2-0-to-work/feed/</wfw:commentRss>
		<slash:comments>22</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/23d331104db3abfa657e102ff301a2d6?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">joelmats</media:title>
		</media:content>
	</item>
	</channel>
</rss>
