I have the following relationships between records:
Given a Project record I need a list of all the Countries associated with all the Resources associated with the Project . No country should appear more than once.
To do this ignoring obvious performance issues, I could add a method to Resource :
def countries
resources.flat_map{|resource| resource.countries}.uniq
end
My question is two-fold.
Is there a way of achieving this with a query in a performant way? And if not, how should I handle this situation?
[Update]
@MarekLipka's suggestion is:
resources.includes(:countries).map(&:countries).flatten.uniq
However this results in 60 hits, totalling 0.4 Seconds for 20 Projects:
Resource Load (1.2ms) SELECT "resources".* FROM "resources" WHERE "resources"."project_id" = 20 ORDER BY name
ResourceLocation Load (1.0ms) SELECT "resource_locations".* FROM "resource_locations" WHERE "resource_locations"."resource_id" IN (97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126)
Country Load (0.4ms) SELECT "countries".* FROM "countries" WHERE "countries"."id" IN (19, 31, 64, 82, 197, 169, 1, 161, 167)
[Update]
My latest attempt comes in about twice as fast as the above solution through using joins
rather than includes
, making 1 hit per resource in a total of ~0.2 seconds:
Country.joins(resource_locations: {resource: :project}).where(resources: {project_id: self}).uniq
This should be ok:
resources.includes(:countries).map(&:countries).flatten.uniq
includes
method resolves the problem of N+1 queries by pre-loading appropriate associations.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.