惟一的值从一个ActiveRecordhas_many协会 - Pluck unique values from an ActiveRecord has_many association

- 此内容更新于:2016-02-01
主题:

我有以下协会:。因此,我可以通过做一个艺术家的歌曲:但是,我想要只歌曲的体裁:但是,这类型可能出现多次的结果;我只会喜欢独特的类型的值。不幸的是,没有任何帮助,因为它返回一个数组,并呼吁它不会调整ActiveRecord查询,但平原。我可以这样做:但我觉得必须有一个更好的方法。注::从最小的基准,然而,似乎有点快。

原文:

I have the following association: Artist has_many Songs. Hence, I can get an artist's songs by doing:

artist.songs

However, I would like to get only the songs' genre:

artist.songs.pluck(:genre)

But, this genre may appear multiple times in the results; I would only like to get unique genre values. Unfortunately, pluck isn't of any help here, since it returns an array, and calling uniq on it won't tweak the ActiveRecord query, but the plain Array#uniq.

I can do it like this:

artist.songs.select(:genre).uniq.pluck(:genre)

but I feel there must be a better way.

P.S.: From some minimal benchmarks, however, pluck + Array#uniq seems a bit faster than select + uniq + pluck.

网友:你确定不调整ActiveRecord查询?

(原文:Are you sure that uniq does not tweak the ActiveRecord query?)

解决方案:
如果使用艺术家协会,你可以,然后映射结果只返回字符串:结果查询:您还可以使用uniq如果呼吁这首歌模型直接而缩小到艺术家:查询结果:都是同样的、高效的和做唯一性的操作在SQL和Ruby。
原文:

If using the artist's songs association, you can select distinct on genre, then map over the results to just return the strings:

artist.songs.select('distinct genre').map(&:genre)
# or...
artist.songs.select(:genre).uniq.map(&:genre) # uniq or distinct work

resulting query:

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

You could also use uniq if calling on the Song model directly while narrowing to the artist:

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

resulting query:

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

Both are equally and efficient and do the uniqueness operation in SQL and not in Ruby.

楼主:Esentially你建议使用代替。他们差不多,因为大量的相关记录我想比。

(原文:Esentially you're suggesting using select + uniq + Array#map instead of select + uniq + pluck. They're pretty much the same; for a large number of associated records I guess pluck does better than Array#map.)

解决方案:
这个生成的SQl查询,而不是查询。uniq再次数组。
原文:
Model.uniq.pluck(:genre)  

this generates SQl query SELECT DISTINCT rather than querying .uniq to an array again.

楼主:我提到我用这个协会,不直接在模型上一样的工作。

(原文:I've mentioned that I am using this on an association, which does not work the same as directly on the model.)