我有3个关联的表:coveralls.io
,Elment
和Measurement
。
元素Image
度量
度量has_many
图像,也包括图像has_many
度量(N-N关联)
如何减少
中的查询数量has_many
对于此代码,每次测量都有N个查询。我可以用这样的东西最小化吗:
images = @element.measurements.map {|e| e.images}.reject!(&:blank?)
images.flatten.map {|i| i.file.url}
查询:`
@element.measurements.joins(:images).select('images.file')
答案 0 :(得分:1)
在这里逐步替换:
images = @element.measurements.map {|e| e.images}.reject!(&:blank?)
对于这一行代码,最好产生下一个关系
has_many :images, through: :measurements
# OR for better naming
has_many :measurement_images, through: :measurements, source: :images
然后您可以做:
images = @element.measurement_images
哪个将执行下一个SQL
SELECT *
FROM images
INNER JOIN measurements
ON measurements.id = images.measurement_id
WHERE measurements.element_id = $1
因此无需INNER JOIN
来拒绝空白图像,只需这样做即可,丢弃不匹配的记录,检出the doc
在创建此has_many through
关系之后,下一个代码将不会产生任何N + 1个问题:
images.map {|i| i.file.url}
此外,您可以通过添加#select
来最小化输出,但是我不建议您这样做,因为它会使代码变得非常复杂,并且与图像库的实现紧密相关,因此在更新库的情况下,您可以破坏密码。
但请注意,如果您将paperclip
gem与默认的URL生成模式一起使用,则可以执行以下操作:
image_ulrs = @element
.measurement_images
.select(
:id,
:type, # if you have STI model
:<your_file_field>_file_name,
:<your_file_field>_updated_at
).map { |i| i.file.url }
<your_file_field>
是第一个传递给has_attached_file
的参数,例如
has_attached_file :attachment
将导致
...
.select(
:id,
:type, # if you have STI model
:attachment_file_name,
:attachment_updated_at
)
但是我再次不建议这样做,因为它不会带来很多性能改进,但将来可能会令人头疼。