Рубин на рельсы фильтрации pg_search_scope v2.2

голоса
46

Я очень новой для Ruby On Rails, и мне нужно помочь выяснить, как изменить существующий запрос дб. Я использую старые версии, которые я не могу обновить: рубин 2.2.3p173 и Rails 4.0.2.

Я хочу, чтобы фильтровать существующие результаты запроса, чтобы удалить записи, которые не имеют ни одного видео. Иерархия модели я думаю: Художник, AlbumGroup, альбом, трек, видео.

Для уточнения: я хочу художник, по крайней мере, 1 видео, от модели ассоциации художника-> AlbumGroup-> albums-> tracks-> видео (не художники> видео).

Существующий запрос содержится в модели Автор:

require_dependency tagging
require_dependency similar
class Artist < ActiveRecord::Base
  has_many :images, dependent: :destroy
  has_many :taggings, dependent: :destroy
  has_many :artforms, through: :taggings
  has_many :similars, foreign_key: similar_id, dependent: :destroy
  has_many :similar_artists, through: :similars, source: :similar_to
  has_many :reverse_similars, foreign_key: similar_to_id, class_name: Similar, dependent: :destroy
  has_many :similar_to_artists, through: :reverse_similars, source: :similar
  has_many :memberships, foreign_key: member_id, dependent: :destroy
  has_many :groups, through: :memberships, source: :membership
  has_many :group_members, foreign_key: membership_id, class_name: Membership, dependent: :destroy
  has_many :members, through: :group_members, source: :member
  has_many :users, through: :followed_artists
  has_many :videos, dependent: :destroy
  has_many :audios, dependent: :destroy
  has_many :metrics, through: :audios
  has_many :releases, foreign_key: 'artist_id', class_name: AlbumGroup
  has_many :albums
  has_many :collaborations
  has_many :album_groups, through: :collaborations
  mount_uploader :mugshot, MugshotUploader
  include PgSearch
  pg_search_scope :for_name,
      against: :name,
      using: { tsearch: {threshold: '1', dictionary: 'simple', tsvector_column: 'tsv_name', prefix: true, normalization: 2}},
      ranked_by: (artists.popularity / 50 * :tsearch) + :tsearch
end

Я хочу добавить что-то вроде следующего, чтобы отфильтровать записи, которые не имеют каких-либо видео: (в запросе):

if: artist.releases.albums.tracks.videos.count > 1

Или художник модель может быть ?:

scope :valid, -> {where(video_count > 1)}

Другой код для различных моделей ниже:

class AlbumGroup < ActiveRecord::Base
  belongs_to :artist
  has_many :collaborations
  has_many :artists, through: :collaborations
  has_many :albums
  has_many :taggings, dependent: :destroy
  has_many :artforms, through: :taggings
  mount_uploader :artwork, MugshotUploader
  def as_json options={}
    {
      id: id,
      title: title
    }
  end
end

class Album < ActiveRecord::Base
  belongs_to :album_group
  belongs_to :artist
  has_many :tracks
end

class Track < ActiveRecord::Base
  has_many :playlist_tracks, dependent: :destroy
  has_many :playlists, through: :playlist_tracks
  belongs_to :audio
  belongs_to :video
  has_many :videos
  has_many :audios
  has_many :taggings, dependent: :destroy
  has_many :artforms, through: :taggings
  belongs_to :album
  belongs_to :artist
  default_scope order: position ASC
  after_save :cache_columns

  def cache_columns
    if image_url.nil?
      img = album.album_group.artwork_url(:tiny)
      unless img.nil?
        update_column(:image_url,img)
      end
    end
    if artist_name.nil?
      if artist_id
        name = Artist.find(artist_id).name
        update_column(:artist_name,name)
      end
    end
    if album_name.nil?
      if album_id
        title = Album.find(album_id).title
        update_column(:album_name,title)
      end
    end
  end
end

class Video < ActiveRecord::Base
  belongs_to :artist
  belongs_to :event
  belongs_to :track
  has_many :tracks
  has_many :playlists, through: :tracks, order: tracks.position ASC
  scope :valid, -> {where(flag_count < 2).order(score DESC) }
  scope :flagged, -> {where(flag_count > ?, 1) }
#   validates :url, uniqueness: {scope: :artist_id}
end
Задан 07/11/2017 в 14:20
пользователем
На других языках...                            


2 ответов

голоса
0

ActiveRecord - х has_manyи belongs_toметоды дают возможность определять области непосредственно на ассоциации. Таким образом, вы можете настроить SQL , который генерируется при доступе к ассоциации.

скажем, вы хотите, чтобы определить область на модели художника, который возвращает все художники, которые имеют нулевое видео. В Rails 5, чтобы найти все художники, которые не имеют видео, вы можете использоватьleft_outer_joins

class Artist < ActiveRecord::Base
  has_many :videos
  scope :with_zero_videos, -> { left_outer_joins(:videos).where(videos: {id: nil}) }
end

Другим хорошим решением является использование includesтак:

Artist.includes(:videos).where(videos: { videos_id: nil })

Вы можете выбрать тот, который вам нравится больше всего!

Надеюсь, что это помогло.

Ответил 07/11/2017 в 15:12
источник пользователем

голоса
0

Благодаря Габриэль, я добавил необработанный запрос SQL для artists_controller.rb, который выглядит как:

  def index
    #artists = Artist.for_name(params[:name])
    artists = Artist.find_by_sql ["SELECT artists.*, ((artists.popularity / 50 * (ts_rank((artists.tsv_name), (to_tsquery('simple', ''' ' || ? || ' ''' || ':*')), 2))) + (ts_rank((artists.tsv_name), (to_tsquery('simple', ''' ' || ? || ' ''' || ':*')), 2))) AS pg_search_rank FROM artists " +
      "JOIN album_groups on (artists.id = album_groups.artist_id) " +
      "JOIN tracks on (tracks.album_group_id = album_groups.id) " +
      "JOIN videos on (videos.track_id = tracks.id) " +
      "WHERE (((artists.tsv_name) @@ (to_tsquery('simple', ''' ' || ? || ' ''' || ':*')))) " +
      "GROUP BY artists.id " +
      "ORDER BY pg_search_rank DESC, artists.id ASC", params[:name], params[:name], params[:name]]
    render json: artists, each_serializer: SimpleArtistSerializer
  end
Ответил 08/11/2017 в 13:42
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more