从ActiveRecord has_many关联中获取唯一值

lin*_*ndy 3 ruby activerecord ruby-on-rails

我有以下关联:Artist has_many Songs.因此,我可以通过以下方式获得艺术家的歌曲:

artist.songs
Run Code Online (Sandbox Code Playgroud)

但是,我想只获得歌曲的类型:

artist.songs.pluck(:genre)
Run Code Online (Sandbox Code Playgroud)

但是,这种类型可能会在结果中出现多次; 我只想获得独特的流派价值观.不幸的是,pluck这里没有任何帮助,因为它返回一个数组,并且调用uniq它不会调整ActiveRecord查询,但是普通的Array#uniq.

我可以这样做:

artist.songs.select(:genre).uniq.pluck(:genre)
Run Code Online (Sandbox Code Playgroud)

但我觉得必须有更好的方法.

PS:然而,从一些最小的基准测试来看,pluck + Array#uniq似乎要快一些select + uniq + pluck.

sbe*_*ker 5

如果使用艺术家的songs关联,您可以select distinct打开genre,然后映射结果以返回字符串:

artist.songs.select('distinct genre').map(&:genre)
# or...
artist.songs.select(:genre).uniq.map(&:genre) # uniq or distinct work
Run Code Online (Sandbox Code Playgroud)

结果查询:

(0.2ms) SELECT distinct genre FROM "songs" WHERE "songs"."artist_id" = ? [["artist_id", 1]]

如果在缩小到艺术家的同时直接调用Song模型,您也可以使用uniq:

Song.where(artist: artist).uniq.pluck(:genre)

结果查询:

(0.2ms) SELECT DISTINCT "songs"."genre" FROM "songs" WHERE "songs"."artist_id" = 1

两者都是同等有效的,并且在SQL中执行唯一性操作,而不是在Ruby中.