#<Arel::Nodes::SqlLiteral> 没有方法错误'map'



我有以下示例查询:

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 

Arel::Nodes:SqlLiteral`的NoMethodError: undefined method映射中的结果

我很欣赏这个查询很傻,但是非simplefieid查询有点太复杂了,无法复制,这是我能创建的最小崩溃版本。有什么想法吗?

您能在该对象上调用all以将其强制转换为Array吗?

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文档中"热切加载"部分的末尾。

我的建议

如果联接不影响外部查询中返回的行数,我认为最好的办法是执行一个查询来获得计数,执行一个询问来获得实际结果。在我们的分页应用程序中,我们必须执行类似的操作:一个查询返回当前页面的结果,另一个查询则返回与筛选条件匹配的记录总数。

问题是Rails#24193https://github.com/rails/rails/issues/24193并且与CCD_ 10结合急切加载有关。解决方法是使用以下形式:Item.select("items.*").from([Arel.sql(source)]).includes([:images])

相关内容

最新更新