我有以下示例查询:
source = "(SELECT DISTINCT source.* FROM (SELECT * FROM items) AS source) AS items"
items = Item.select("items.*").from(source).includes([:images])
p items # [#<Item id: 1>, #<Item id:2>]
然而运行:
p items.count
NoMethodError: undefined method
map' for Arel::Nodes::SqlLiteral` 的结果
我很欣赏这个查询很愚蠢,但是非简化查询有点太复杂而无法复制,这是我能创建的最小的崩溃版本。有什么想法吗?
最佳答案
您能否对该对象调用 all
以将其转换为数组?
Item.select("items.*").from(source).includes([:images]).all.count
或者在那种情况下,size
可能更合适。在任何情况下,这都会执行查询并将所有对象加载到内存中,这可能是不可取的。
看起来问题出在您的 includes([:images])
上。在类似的应用程序上,我可以从控制台执行此操作:
> Category.select('categories.*').from('(SELECT DISTINCT source.* FROM (SELECT * FROM categories) AS source) AS categories').count
(0.5ms) SELECT COUNT(*) FROM (SELECT DISTINCT source.* FROM (SELECT * FROM categories) AS source) AS categories
(请注意,count
覆盖了 SELECT 子句,即使我明确指定了 items.*
。但它们仍然是等效查询。)
一旦我添加了一个 includes
作用域,它就失败了:
> Category.select('categories.*').from('(SELECT DISTINCT source.* FROM (SELECT * FROM categories) AS source) AS categories').includes(:projects).count
NoMethodError: undefined method `left' for #<Arel::Nodes::SqlLiteral:0x131d35248>
我尝试了几种不同的获取计数的方法,比如 select('COUNT(categories.*)')
,但它们都以各种方式失败了。 ActiveRecord 似乎退回到基本的 LEFT OUTER JOIN 来执行预加载,可能是因为它认为您正在使用某种条件或外部表来执行连接,这似乎混淆了它执行计数的正常方法.请参阅 ActiveRecord::Associations
docs 中关于预加载部分的结尾。 .
我的建议
如果连接不影响外部查询中返回的行数,我认为最好的办法是执行一个查询来获取计数,再执行一个查询来获取实际结果。我们必须在我们的分页应用程序中做类似的事情:一个查询返回当前结果页,一个返回符合过滤条件的记录总数。
关于ruby-on-rails - #<Arel::Nodes::SqlLiteral> 没有方法错误 'map',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9304587/