Reputation: 27192
I'm using the Geocoder and Sunspot gem in my application and I have a field called :search_near_address
that is suppose to give users the ability to input an address they want to search near within X amount of miles
. What I am trying to map to is my Stores :address
to use for the :search_near_address
field. This way users can input an address ( i.e. 451 University Avenue, Palo Alto, CA ) in the :search_near_address
field and it will search in a radius of 50 miles.
Sunspot 1.2.1
class Store < ActiveRecord::Base
attr_accessible :address, :latitude, :longitude
has_many :products
geocoded_by :address
after_validation :geocode
reverse_geocoded_by :latitude, :longitude
after_validation :reverse_geocode
end
class Product < ActiveRecord::Base
belongs_to :store
searchable do # Searching with product model.
string :search_near # For rake sunspot:reindex
location :location
end
def search_near_address
store.address if store # You may have to use the "if store".
end
def location
# may need the "if store" after longitude)....
Sunspot::Util::Coordinates.new(store.latitude, store.longitude)
end
end
class SearchController < ApplicationController
def index
@search = Product.search do |q| # Search with sunspot
q.fulltext params[:search]
q.with(:location).near(*Geocoder.coordinates(params[:search_near_address]), :precision => 4) if params[:search_near_address].present?
end
@products = @search.results # Return results from Product.search block.
end
end
# search/index/html.erb
<%= form_tag results_search_index_path, :method => 'get' do %>
<%= text_field_tag :search, params[:search] %>
<%= text_field_tag :search_near_address, params[:search_near_address] %>
<%= submit_tag "Go", :name => nil %>
<% end %>
Upvotes: 2
Views: 2165
Reputation: 3130
First what @m_x said is right, you can't expect assigning the Store#near results to the @search object would work....
Just reading the docs about Geospatial in https://github.com/sunspot/sunspot, you can clearly see that you are missing a few things:
You have to declare your Geospatial field using the latitude and longitude fields that geocoder requires:
class Product < ActiveRecord::Base
belongs_to :store
searchable do # for Sunspot search.
string :search_near
latlon(:location) {
Sunspot::Util::Coordinates.new(category.latitude, category.longitude)
}
end
def search_near
#I changed this because business_store will not work out.
store.address
end
end
Then you can search (after having indexed something) like this:
class SearchController < ApplicationController
def index
# Search with sunspot
@search = Sunspot.search(Product) do
fulltext params[:search]
# The "*" pop off the elements of the array that
# Geocoder.coordinates returns.
with(:location).near(*Geocoder.coordinates(params[:search_near]),
:precision => 6)
# NOTE: You could also use the in_radius method but only in the pre-release version:
# with(:location).in_radius(*Geocoder.coordinates(params[:search_near]), 100) if params[:search_near].present?
end
# Return results from Product.search block.
@products = @search.results
end
end
Also read about the :precision option here http://sunspot.github.com/docs/Sunspot/DSL/RestrictionWithNear.html#near-instance_method
About Geocoder https://github.com/alexreisner/geocoder
Upvotes: 7
Reputation: 566
Not sure I fully understand what it is your attempting with the above but I have a similar situation in trying to get geocoder and sunspot to play together.
This is untested as yet but this is my current thinking....
Event.search do
keywords search_terms
any_of do
with(:id).any_of(Event.near(coordinates,50).map(&:id))
end
end.results
Essentially I'm trying to combine the two result sets to only bring back the results that match both the distance and keyword terms.
Hope this is of help to someone at least.
Upvotes: 3