module JamRuby # not a active_record model; just a search result class Search attr_accessor :bands, :musicians, :fans, :recordings, :friends PARAM_MUSICIAN = :search_m LIMIT = 10 M_PER_PAGE = 20 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 sel_str = 'users.*' case ordering = self.musician_order_param(params) when :plays when :followed sel_str = "COUNT(follows) AS search_follow_count, #{sel_str}" 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, users.created_at DESC") when :playing end rel = rel.joins("LEFT JOIN friendships AS friends ON friends.user_id = users.id") sel_str = "#{sel_str}, COUNT(friends) AS search_friend_count" rel = rel.joins("LEFT JOIN recordings AS records ON records.owner_id = users.id") sel_str = "#{sel_str}, COUNT(records) AS search_recording_count" rel = rel.joins("LEFT JOIN music_sessions AS sessions ON sessions.user_id = users.id") sel_str = "#{sel_str}, COUNT(sessions) AS search_session_count" rel = rel.select(sel_str) perpage = params[:per_page] || M_PER_PAGE page = [params[:page].to_i, 1].max rel = rel.paginate(:page => page, :per_page => perpage) rel.includes([:instruments, :followings]) Search.new(rel.all) 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