【发布时间】:2015-01-16 22:44:51
【问题描述】:
我正在尝试将“原始”PostGIS SQL 查询转换为 Rails ActiveRecord 查询。我的目标是将两个连续的 ActiveRecord 查询(每个约 1 毫秒)转换为单个 ActiveRecord 查询(约 1 毫秒)。使用下面的 SQL 和 ActiveRecord::Base.connection.execute 我能够验证时间减少。
因此,我的直接请求是帮助我将此查询转换为 ActiveRecord 查询(以及执行它的最佳方式)。
SELECT COUNT(*)
FROM "users"
INNER JOIN (
SELECT "centroid"
FROM "zip_caches"
WHERE "zip_caches"."postalcode" = '<postalcode>'
) AS "sub" ON ST_Intersects("users"."vendor_coverage", "sub"."centroid")
WHERE "users"."active" = 1;
注意值 <postalcode> 是此查询中唯一的变量数据。显然,这里有两个模型User 和ZipCache。 User 与 ZipCache 没有直接关系。
当前的两步 ActiveRecord 查询如下所示。
zip = ZipCache.select(:centroid).where(postalcode: '<postalcode>').limit(1).first
User.where{st_intersects(vendor_coverage, zip.centroid)}.count
【问题讨论】:
-
我学到的最重要的技巧之一是,虽然你可以在 Ruby 中链接方法很好,但如果你在代码中链接,则表明你没有遵循Law Of Demeter。不要从查看 SQL 查询开始,您应该查看 ZipCache.select.where.limit.first 并了解如何通过向下移动逻辑来减少方法的数量。您从 ZipCache 而不是 User 模型开始处理查询,这有点奇怪......我错过了什么吗?
-
我认为您“缺少”的部分是因为它是 ActiveRecord 链接是必需的。我敢于编写一个 ActiveRecord 查询,它只选择和填充一个模型和一个属性,并告诉我如何在没有方法链接的情况下执行此操作。有些东西告诉我你对 LoD 很迂腐。已经说过很多次了,但需要重复The Law of Demeter Is Not A Dot Counting Exercise。
标签: ruby activerecord postgis arel rgeo