12

我一直坚持这一点,当然这很容易,但我只是在文档中找不到解决方案。

我有一些树结构和子 where 子句,我必须使用“exists”子查询进行过滤:

current_node.children.as("children_nodes").where(Node.where(...).exists)

Node.where.clause 已经加入 children_nodes,如果我使用两种不同的模型,它就可以工作。但是如何使用别名?上面的代码将导致:

NoMethodError (undefined method `where' for #<Arel::Nodes::TableAlias

它是如此基本,但我缺少一些东西(我对 arel 太陌生了)。

4

3 回答 3

3

您也许可以使用table_alias可以在 Arel::Table 上调用的属性。

例子:

# works
users = User.arel_table
some_other_table = Post.arel_table
users.table_alias = 'people'
users.join(some_other_table)

# doesn't work
users = User.arel_table.alias('people')
some_other_table = Post.arel_table
users.join(some_other_table)
于 2018-01-05T17:55:33.763 回答
0

as 方法生成一个没有 where 方法的 arel 对象,例如 Relation 对象 Arel 对象生成一个要执行的 sql,基本上它是一个选择管理器,您可以使用 union 并给它另一个条件,然后使用 to_sql 例如:

arel_obj = current_node.children.as("children_nodes").Union(Node.where(....)

sql_string = arel_obj.to_sql

Node.find_by_sql(sql_string)

这里有一些可能有帮助的链接 http://www.rubydoc.info/github/rails/arel/Arel/SelectManager

于 2014-10-28T14:55:27.040 回答
0

在 Arel 中,as将使用该点的所有内容并使用它来创建一个命名的子查询,您可以将其放入FROM子句中。例如,current_node.children.as("children_nodes").to_sql将打印如下内容:

(SELECT nodes.* FROM nodes WHERE nodes.parent_id = 5) AS children_nodes

但听起来你真正想要的是给nodes表一个 SQL 别名。从技术上讲,你可以这样做from

current_node.children.from("nodes AS children_nodes").to_sql

但是如果你这样做了,很多其他的事情都会被破坏,因为查询的其余部分仍在尝试SELECT nodes.*过滤WHERE nodes.parent_id = 5

所以我认为更好的选择是避免使用别名,或者使用以下方式编写查询find_by_sql

Node.find_by_sql <<-EOQ
    SELECT n.*
    FROM   nodes n
    WHERE  n.parent_id = 5
    AND EXISTS (SELECT 1
                FROM   nodes n2
                WHERE  ....)
EOQ

也许您也可以通过给内部表起别名来使事情正常进行:

current_node.children.where(
  Node.from("nodes n").where("...").select("1").exists
)
于 2016-02-17T01:36:38.580 回答