I have a model User and Listing in my rails app. User has many listings and listing belongs to user. I also have a attribute name rating in user table. What I want is to search the keyword in Listing model and order it based on rating attribute of User model.
This is what I have in Listing model
searchable do
text :title, :default_boost => 3
text :description, :default_boost => 2
integer :category_id, :references => Category
integer :subcategory_id, :references => Subcategory
string :zipcode
time :created_at
double :user do
user.rating
end
end
And this is how I am trying to search
#search = Sunspot.search(Listing) do
keywords params[:q] do
fields :title
end
order_by THIS IS WHERE I NEED HELP
paginate :page => params[:page], :per_page => 20
end
You will need to add the keyword and rating attributes to the listing searachable method.
class Listing < ActiveRecord::Base
belongs_to :user
searchable do
text :keyword
integer :rating { user.rating }
end
end
Then in your search action in your controller
Listing.search do
fulltext params[:q]
order_by :rating, :desc
end
See http://sunspot.github.com/ for more examples.
Looking at your code, you need to change in your searchable method
double :user do
user.rating
end
to
double :rating do
user.rating
end
Related
I am trying to set search on a model that has a lot of different associations. I am starting with the belongs_to associations. I am able to search on the name field of the Product model successfully but the when I perform a search on what would be in the associated models I just get the default results.
What am I doing wrong?
Any help would be much appreciated.
#Product Model
Class Product < ActiveRecord::Base
searchable do
text :name
integer :store_id, :references => Store.name
text :store do
Store.all.map { |store| store.name }
end
end
end
#product controler
def search
#search = Sunspot.search(Product) do
fulltext params[:search] do
fields(:name, :store)
end
end
#products = #search.results
end
#Store Model
searchable do
text :name
end
Class Product < ActiveRecord::Base
belongs_to :store
searchable do
text :name
index :store do
index :name
end
integer :store_id # do you really need this? I think not.
end
end
Don't forget to reindex after each change in your models.
EDIT: You don't need to index the Store class by itself, unless you plan to search on it.
Here is what my initial searchable block looks like in my User model:
searchable do
text :name
integer :sport_ids, multiple: true do
sports.map(&:id)
end
integer :position_ids, multiple: true do
positions.map(&:id)
end
integer :city_id
integer :school_id
string :state
end
How do I search by has_many associations? I need it to return each Athlete who has a specified ID in their sports or sport_positions. So if someone selects "Basketball" from a dropdown, ID of 2 is passed to my search method and it needs to return Athletes who have sport_id of 2 in their collection of sport_ids. Here is how sports and sport_positions are declared in the User model:
has_and_belongs_to_many :positions, :class_name => "SportPosition", :join_table => "user_sport_positions", :uniq => true
has_many :sports, :through => :user_sports, order: "user_sports.created_at", class_name: "Sport"
has_many :user_sports
:::EDIT:::
This worked for a minute after I reindexed, then all of a sudden I started getting this error:
Sunspot::UnrecognizedFieldError (No field configured for Athlete with name 'sport_ids'):
app/models/search.rb:12:in `block in execute'
here is my Search model:
class Search < ActiveRecord::Base
attr_accessible :coach_id, :sport_id, :gpa_min, :gpa_max, :sport_position_id,
:classification, :city_id, :state, :school_id, :athlete_name
belongs_to :coach
def self.execute(params, page = nil)
Sunspot.search(Athlete) do |query|
query.with :public, true
query.with :removed_from_listing, false
query.fulltext params[:athlete_name] unless params[:athlete_name].blank?
query.with :sport_ids, params[:sport_id] unless params[:sport_id].blank?
query.with :position_ids, params[:sport_position_id] unless params[:sport_position_id].blank?
query.with(:state).equal_to(params[:state]) unless params[:state].blank?
query.with(:classification).equal_to(params[:classification]) unless params[:classification].blank?
query.with :city_id, params[:city_id] unless params[:city_id].blank?
query.with :school_id, params[:school_id] unless params[:school_id].blank?
query.with(:current_gpa).between(params[:gpa_min]..params[:gpa_max]) unless params[:gpa_min].eql?("0.0") && params[:gpa_max].eql?("5.0")
query.paginate page: page unless page.blank?
end
end
end
NOTE: To make this even more strange, I have a field called "recruit_year" that is an integer attribute. I was getting the same error on this field saying "No field configured" blah blah. That error usually only happens on text fields if you try to do a comparison like equal_to or treat it like a string.
Help?
This works fine, the problem was STI. I had an Athlete block that was overriding the User block.
I'm trying to search Products using solr and it's working well. Except that I want to restrict the suppliers, associated with Products by has_and_belongs_to_many, using the status field in Supplier model being 0 or 1.
My models are:
"Product.rb"
has_and_belongs_to_many :suppliers, :class_name => 'Company'
searchable do
text :name
text :brand
text :description
end
"Company.rb"
attr_accessible :status
has_and_belongs_to_many :products
For search I'm using:
#search = Product.search(:include => :suppliers) do
fulltext params[:s]
with :status, 1 # This gives error as status is not a field in Product
end
How can I include only those suppliers with status 1?
You're missing the status in the searchable
searchable do
text :name
text :brand
text :description
boolean :status
end
I figured that instead of leaving certain attributes in parent and embedded documents nil/null (e.g. total of an order if no price exists), I better not save them at all. How can I remove attributes that are nil before saving?
# embedded order position for each order
class Orderitem
include Mongoid::Document
field :quantity, :type => Integer
field :unit_price, :type => Integer
field :total, :type => Integer
field :economical_potential, :type => Integer
embedded_in :order
belongs_to :supplier
belongs_to :item
before_save :remove_empty_fields
private
def remove_empty_fields
attributes.each do |attr_name, value|
if value.nil?
# don't save attribute
end
end
end
end
Why do you want to remove attributes from your model? In that case, I would add another model called unit and add :price as an attribute. Then add a function to Orderitem called def total_of_unit which will return the total based on the number of units and their price.
In code it would look like this:
class Orderitem
...
field :quantity, :type => Integer
# drop :unit_price
# drop :total
field :economical_potential, :type => Integer
...
has_many :units
...
def total
#total = 0
self.units.each do |unit|
#total = #total + unit.price
end
return #total
end
end
Unit would look like this:
class Unit
field :unit_price, :type => Integer
belongs_to :Orderitem
end
Mongoid supports #unset, so you can use something like this:
order_item.unset(:total)
In my app I am using Sunspot for a fulltext search. The problem is that I want to have sorting by association model field. In my case:
class Movie < ActiveRecord::Base
attr_accessible :description, :genre, :name
has_many :premieres
end
and my Premier model has:
belongs_to :movie
Searching by movie name is done by defining the method:
def movie_name
movie.name
end
but when I try to do:
order_by :movie_name, :asc
It says:
No field configured for Premiere with name 'movie_name'
How do I make this sorting available?
you can do it like this
searchable auto_index: true do
text :movie_name do
if self.movie.present?
self.movie.name
end
end
end
then you can use
order_by :movie_name, :asc