【问题标题】:ruby on rails filtering pg_search_scope v2.2ruby on rails 过滤 pg_search_scope v2.2
【发布时间】:2018-04-20 03:16:33
【问题描述】:

我是 Ruby on Rails 的新手,我需要帮助弄清楚如何修改现有的数据库查询。我正在使用无法更新的旧版本:Ruby 2.2.3p173 和 Rails 4.0.2。

我想过滤现有的查询结果以删除没有任何视频的记录。我认为的模型层次结构是:Artist、AlbumGroup、Album、Track、Video。

澄清一下:我希望艺术家至少有 1 个视频,来自模型协会艺术家->专辑组->专辑->曲目->视频(不是艺术家->视频)。

现有查询包含在模型 Artist 中:

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

【问题讨论】:

  • 您是否出现了一些错误?这个范围 :valid, -> {where("video_count > 1")} 在我看来可以作为解决方案
  • 范围代码不会导致错误,但它似乎不起作用。我是根据各种谷歌搜索来猜测代码,所以我不知道“video_count”是否有效
  • 要查找没有视频的元素并删除?
  • 不,这只是一个只读查询,不影响数据

标签: ruby-on-rails ruby pg-search


【解决方案1】:

ActiveRecord 的has_manybelongs_to 方法使您能够直接在关联上定义范围。这样,您可以自定义访问关联时生成的 SQL。

假设您想在 Artist 模型上定义一个范围,它返回所有视频为零的艺术家。在 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 })

你可以选择你最喜欢的!

希望对您有所帮助。

【讨论】:

  • 好的,所以 cmets 不适合在...中编写代码。我添加了 Artists = Artist.include(:videos).where(videos: {videos_id: nil}) 到我的 ArtistsController 和我得到一个错误:错误的参数类型符号(预期的模块)
  • 范围解决方案不报错但不影响生成的SQL查询,即:SELECT "artists".*, ((artists.popularity / 50 * (ts_rank(("artists) "."tsv_name"), (to_tsquery('simple', ''' ' || 'oasis' || '''' || ':*')), 2))) + (ts_rank(("艺术家" ."tsv_name"), (to_tsquery('simple', ''' ' || 'oasis' || '''' || ':*')), 2))) AS pg_search_rank FROM "artists" WHERE (( ("艺术家"."tsv_name") @@ (to_tsquery('simple', ''' ' || 'oasis' || ' ''' || ':*')))) 按 pg_search_rank DESC 排序,"艺术家"."id" ASC
  • 所以我有点迷路了,我以为你只需要一个查询来检索所有包含空视频的艺术家。范围查询和你展示的这个 SQL 查询有什么关系?
  • 对不起,我的英文可能有点模棱两可“我想过滤现有的查询结果以删除没有任何视频的记录”,这意味着我想查询至少有1 个视频(它是艺术家->专辑组->专辑->曲目->视频关联,而不是艺术家->视频)。我希望这更清楚
  • 是 pg_search_scope 的要求吗?我认为您需要执行一些连接,并且 pg_search gems 说现在,不支持比一个关联更深入的搜索。看看这里:github.com/Casecommons/pg_search
【解决方案2】:

感谢 Gabriel,我已将原始 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-12-15
    • 1970-01-01
    • 1970-01-01
    • 2012-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多