diff --git a/db/manifest b/db/manifest index 9b209f892..be8d928cd 100755 --- a/db/manifest +++ b/db/manifest @@ -303,4 +303,5 @@ jam_track_name_drop_unique.sql jam_track_searchability.sql harry_fox_agency.sql jam_track_slug.sql -mixdown.sql \ No newline at end of file +mixdown.sql +jam_track_lang_idx.sql diff --git a/db/up/jam_track_lang_idx.sql b/db/up/jam_track_lang_idx.sql new file mode 100644 index 000000000..aa5c84c26 --- /dev/null +++ b/db/up/jam_track_lang_idx.sql @@ -0,0 +1 @@ +CREATE INDEX ON jam_tracks(language); diff --git a/ruby/lib/jam_ruby/models/base_search.rb b/ruby/lib/jam_ruby/models/base_search.rb index ed2feefb7..685133be8 100644 --- a/ruby/lib/jam_ruby/models/base_search.rb +++ b/ruby/lib/jam_ruby/models/base_search.rb @@ -102,11 +102,19 @@ module JamRuby def self.search_target_class end + def self.genre_ids + @@genre_ids ||= Hash[ *Genre.pluck(:id).collect { |v| [ v, v ] }.flatten ] + end + + def self.instrument_ids + @@instrument_ids ||= Hash[ *Instrument.pluck(:id).collect { |v| [ v, v ] }.flatten ] + end + def _genres(rel, query_data=json) gids = query_data[KEY_GENRES] unless gids.blank? - allgids = Genre.order(:id).pluck(:id) - gids = gids.select { |gg| allgids.index(gg).present? } + allgids = self.class.genre_ids + gids = gids.select { |gg| allgids.has_key?(gg) } unless gids.blank? gidsql = gids.join("','") @@ -119,8 +127,8 @@ module JamRuby def _instruments(rel, query_data=json) unless (instruments = query_data[KEY_INSTRUMENTS]).blank? - instrids = Instrument.order(:id).pluck(:id) - instruments = instruments.select { |ii| instrids.index(ii['instrument_id']).present? } + instrids = self.class.instrument_ids + instruments = instruments.select { |ii| instrids.has_key?(ii['instrument_id']) } unless instruments.blank? instsql = "SELECT player_id FROM musicians_instruments WHERE ((" diff --git a/ruby/lib/jam_ruby/models/jam_track_search.rb b/ruby/lib/jam_ruby/models/jam_track_search.rb index 424f33dd2..de8f66dc3 100644 --- a/ruby/lib/jam_ruby/models/jam_track_search.rb +++ b/ruby/lib/jam_ruby/models/jam_track_search.rb @@ -4,31 +4,47 @@ module JamRuby cattr_accessor :jschema, :search_meta attr_accessor :user_counters + KEY_QUERY = 'query' KEY_SEARCH_STR = 'search_str' KEY_RESULT_TYPES = 'result_types' KEY_SONGS = 'songs' KEY_ARTISTS = 'artists' KEY_RESULTS = 'results' + KEY_RESULT_SETS = 'result_sets' + KEY_PAGE_NUM = 'page_num' + KEY_TOTAL_COUNT = 'total_count' + KEY_PAGE_COUNT = 'page_count' + KEY_PER_PAGE = 'per_page' + PER_PAGE = 'development'==Rails.env ? 8 : 20 + KEY_GENRES = 'genres' + KEY_INSTRUMENTS = 'instruments' + KEY_LANGUAGE = 'language' def self.json_schema - return @@jschema if @@jschema - @@jschema = { - KEY_SEARCH_STR => '', - KEY_INSTRUMENTS => [], - KEY_GENRES => [], - KEY_RESULT_TYPES => [], - KEY_SONGS => { - 'page_num' => 0, - 'page_count' => 0, + return @@jschema ||= { + KEY_QUERY => { + KEY_SEARCH_STR => '', + KEY_INSTRUMENTS => [], + KEY_GENRES => [], + KEY_LANGUAGE => '', + KEY_RESULT_TYPES => [], + KEY_PAGE_NUM => 1, + KEY_PER_PAGE => PER_PAGE, }, - KEY_ARTISTS => { - 'page_num' => 0, - 'page_count' => 0, + KEY_RESULT_SETS => { + KEY_SONGS => { + KEY_RESULTS => [], + KEY_PAGE_NUM => 1, + KEY_TOTAL_COUNT => 0, + KEY_PAGE_COUNT => 0, + }, + KEY_ARTISTS => { + KEY_RESULTS => [], + KEY_PAGE_NUM => 1, + KEY_TOTAL_COUNT => 0, + KEY_PAGE_COUNT => 0, + }, }, - KEY_RESULTS => { - KEY_SONGS => [], - KEY_ARTISTS => [], - } } end @@ -36,85 +52,106 @@ module JamRuby JamTrack end - def do_search(filter) + def do_search(query) rel = JamTrack.unscoped - unless (vals=filter[KEY_GENRES]).blank? - sqlstr = "'#{vals.join("','")}'" - # sqlstr = ActiveRecord::Base.connection.quote("'#{vals.join("','")}'") - rel = rel.joins(:genres_jam_tracks) - rel = rel.where("genres_jam_tracks.genre_id IN (#{sqlstr})") - end - unless (vals=filter[KEY_INSTRUMENTS]).blank? - sqlstr = "'#{vals.join("','")}'" - # sqlstr = ActiveRecord::Base.connection.quote("'#{vals.join("','")}'") - rel = rel.joins(:jam_track_tracks) - rel = rel.where("jam_track_tracks.instrument_id IN (#{sqlstr})") - rel = rel.where("jam_track_tracks.track_type != 'Master'") + unless (gids = query[KEY_GENRES]).blank? + allgids = self.class.genre_ids + gids = gids.select { |gg| allgids.has_key?(gg) } + + unless gids.blank? + sqlstr = "'#{gids.join("','")}'" + rel = rel.joins(:genres_jam_tracks) + rel = rel.where("genres_jam_tracks.genre_id IN (#{sqlstr})") + end + end + unless (instruments = query[KEY_INSTRUMENTS]).blank? + instrids = self.class.instrument_ids + instruments = instruments.select { |ii| instrids.has_key?(ii['instrument_id']) } + + unless instruments.blank? + sqlstr = "'#{instruments.join("','")}'" + rel = rel.joins(:jam_track_tracks) + rel = rel.where("jam_track_tracks.instrument_id IN (#{sqlstr})") + rel = rel.where("jam_track_tracks.track_type != 'Master'") + end end rel end - SONGS_PER_PAGE = 20 - ARTISTS_PER_PAGE = 20 - - def search_results_page(filter=nil) - result_types = filter[KEY_RESULT_TYPES] - has_songs, has_artists = result_types.index(KEY_SONGS), result_types.index(KEY_ARTISTS) - filter[KEY_RESULTS] = {} - + def search_results_page(query=nil) + filter = { + KEY_QUERY => query, + } + result_types = query[KEY_RESULT_TYPES] + if result_types + has_songs, has_artists = result_types.index(KEY_SONGS), result_types.index(KEY_ARTISTS) + else + has_songs, has_artists = true, true + end + result_sets = filter[KEY_RESULT_SETS] = self.class.json_schema[KEY_RESULT_SETS] if has_songs - rel = do_search(filter) - unless (val=filter[KEY_SEARCH_STR]).blank? + rel = do_search(query) + unless (val = query[KEY_SEARCH_STR]).blank? tsquery = Search.create_tsquery(val) rel = rel.where("(search_tsv @@ to_tsquery('jamenglish', ?))", tsquery) if tsquery end rel = rel.order(:name).includes(:genres) - pgnum = [filter[KEY_SONGS]['page_num'].to_i, 1].max - rel = rel.paginate(:page => pgnum, :per_page => SONGS_PER_PAGE) + pgnum = [query[KEY_PAGE_NUM].to_i, 1].max + rel = rel.paginate(:page => pgnum, :per_page => query[KEY_PER_PAGE]) results = rel.all.collect do |jt| { 'id' => jt.id, - 'song_name' => jt.name, + 'name' => jt.name, 'artist' => jt.original_artist, 'genre' => jt.genres.map(&:description).join(', '), 'year' => '' } end - filter[KEY_SONGS] = { - 'page_num' => pgnum, - 'page_count' => rel.total_pages, + + result_sets[KEY_SONGS] = { + KEY_RESULTS => results, + KEY_PAGE_NUM => pgnum, + KEY_TOTAL_COUNT => rel.total_entries, + KEY_PAGE_COUNT => rel.total_pages, } - filter[KEY_RESULTS][KEY_SONGS] = results end if has_artists - rel = do_search(filter) + rel = do_search(query) rel = rel.select("DISTINCT ON(jam_tracks.original_artist) jam_tracks.id, jam_tracks.original_artist") - unless (val=filter[KEY_SEARCH_STR]).blank? + unless (val = query[KEY_SEARCH_STR]).blank? rel = rel.where("original_artist LIKE ?","%#{val}%") end rel = rel.order(:original_artist) - pgnum = [filter[KEY_ARTISTS]['page_num'].to_i, 1].max - rel = rel.paginate(:page => pgnum, :per_page => ARTISTS_PER_PAGE) + pgnum = [query[KEY_PAGE_NUM].to_i, 1].max + rel = rel.paginate(:page => pgnum, :per_page => query[KEY_PER_PAGE]) results = rel.all.collect do |jt| { 'id' => jt.id, 'artist' => jt.original_artist } end - filter[KEY_ARTISTS] = { - 'page_num' => pgnum, - 'page_count' => rel.total_pages, + + result_sets[KEY_ARTISTS] = { + KEY_RESULTS => results, + KEY_PAGE_NUM => pgnum, + KEY_TOTAL_COUNT => rel.total_entries, + KEY_PAGE_COUNT => rel.total_pages, } - filter[KEY_RESULTS][KEY_ARTISTS] = results end filter end + + def self.all_languages + JamTrack.select("SELECT DISTINCT(language)").order(:language).collect do |lang| + { description: ISO_639.find_by_code(lang), id: lang } + end + end end end diff --git a/web/app/controllers/api_search_controller.rb b/web/app/controllers/api_search_controller.rb index 293462473..49547bd95 100644 --- a/web/app/controllers/api_search_controller.rb +++ b/web/app/controllers/api_search_controller.rb @@ -68,9 +68,15 @@ class ApiSearchController < ApiController def jam_tracks if request.get? - render(json: {}, status: 200) and return + if params[:iso639] + render(json: JamTrackSearch.all_languages.to_json, status: 200) and return + else + render(json: {}, status: 200) and return + end elsif request.post? - result = JamTrackSearch.new.search_results_page(request.params[:api_search]) + jts = JamTrackSearch.new + filter = request.params[:api_search] + result = jts.search_results_page(filter) render(json: result.to_json, status: 200) and return end end diff --git a/web/app/views/api_jam_tracks/show_for_client.rabl b/web/app/views/api_jam_tracks/show_for_client.rabl index 27f4fb616..c2e5874a2 100644 --- a/web/app/views/api_jam_tracks/show_for_client.rabl +++ b/web/app/views/api_jam_tracks/show_for_client.rabl @@ -1,6 +1,6 @@ object @jam_track -attributes :id, :name, :description, :initial_play_silence, :original_artist, :version +attributes :id, :name, :description, :initial_play_silence, :original_artist, :version, :year child(:genres) { attributes :id, :description