jam-cloud/ruby/lib/jam_ruby/models/search.rb

146 lines
4.3 KiB
Ruby

module JamRuby
# not a active_record model; just a search result
class Search
attr_accessor :bands, :musicians, :fans, :recordings, :friends
PARAM_SEARCH_MUSICIAN = :search_m
LIMIT = 10
M_ORDER_FOLLOWS = ['Most Followed', :followed]
M_ORDER_PLAYS = ['Most Plays', :plays]
M_ORDER_PLAYING = ['Playing Now', :playing]
M_ORDERINGS = [M_ORDER_FOLLOWS, M_ORDER_PLAYS, M_ORDER_PLAYING]
M_ORDERING_KEYS = M_ORDERINGS.collect { |oo| oo[1] }
def self.musician_order_param(params)
ordering = params[:orderby]
ordering.blank? ? M_ORDERING_KEYS[0] : M_ORDERING_KEYS.detect { |oo| oo.to_s == ordering }
end
def self.musician_search(params={}, current_user=nil)
rel = User.where(:musician => true)
unless (instrument = params[:instrument]).blank?
rel = rel.joins("RIGHT JOIN musicians_instruments AS minst ON minst.user_id = users.id")
.where(['minst.instrument_id = ? AND users.id IS NOT NULL', instrument])
end
location_distance, location_city = params[:distance], params[:city]
if location_distance && location_city
if geo = MaxMindGeo.where(:city => params[:city]).limit(1).first
citylatlng = [geo.lat, geo.lng]
rel = rel.within(location_distance, :origin => citylatlng)
end
elsif current_user
latlng = []
if current_user.lat.nil?
if params[:remote_ip]
if geo = MaxMindGeo.ip_lookup(params[:remote_ip])
latlng = [geo.lat, geo.lng]
end
end
else
latlng = [current_user.lat, current_user.lng]
end
distance = location_distance || 50
rel = rel.within(distance, :origin => latlng) unless latlng.blank?
end
case ordering = self.musician_order_param(params)
when :plays
when :followed
rel = rel.select("COUNT(follows) AS fcount, users.*")
rel = rel.joins("LEFT JOIN users_followers AS follows ON follows.user_id = users.id")
rel = rel.group("users.id")
rel = rel.order("COUNT(follows) DESC")
when :playing
end
perpage = params[:per_page] || 20
page = [params[:page].to_i, 1].max
rel = rel.paginate(:page => page, :per_page => perpage)
rel.includes([:instruments])
srch = Search.new
srch.musicians = rel.all
srch
end
# performs a site-white search
def self.search(query, user_id = nil)
users = User.search(query, :limit => LIMIT)
bands = Band.search(query, :limit => LIMIT)
# NOTE: I removed recordings from search here. This is because we switched
# to "claimed_recordings" so it's not clear what should be searched.
friends = Friendship.search(query, user_id, :limit => LIMIT)
return Search.new(users + bands + friends)
end
# performs a friend search scoped to a specific user
# def self.search_by_user(query, user_id)
# friends = Friendship.search(query, user_id, :limit => LIMIT)
# return Search.new(friends)
# end
# search_results - results from a Tire search across band/user/recording
def initialize(search_results)
@bands = []
@musicians = []
@fans = []
@recordings = []
@friends = []
if search_results.nil?
return
end
search_results.take(LIMIT).each do |result|
if result.class == User
if result.musician
@musicians.push(result)
else
@fans.push(result)
end
elsif result.class == Band
@bands.push(result)
elsif result.class == Recording
@recordings.push(result)
elsif result.class == Friendship
@friends.push(result.friend)
else
raise Exception, "unknown class #{result.class} returned in search results"
end
end
end
def self.create_tsquery(query)
# empty queries don't hit back to elasticsearch
if query.nil? || query.length == 0
return nil
end
search_terms = query.split
if search_terms.length == 0
return nil
end
args = nil
search_terms.each do |search_term|
if args == nil
args = search_term
else
args = args + " & " + search_term
end
end
args = args + ":*"
return args
end
end
end