Ecto:where子句是什么(理解语法)

Ecto: What is the where clause (understanding the syntax)

我正在浏览一本 Phoenix Liveview 书,我遇到了这一行:

|> where([d], d.user_id == ^user.id)

我正在尝试理解这种语法。我试着查找 Elixir Guards 但这不是其中之一。这里的 [d] 是什么?这是某种匿名函数吗?

这是在以下地方使用的函数:

  def for_user(query \ base(), user) do
    query
    |> where([d], d.user_id == ^user.id)
  end

where是由ecto定义的宏。这就是为什么要使用它你需要 import Ecto.Query,虽然在很多情况下你看不到它,因为你有一个 use MyApp.Schema 或类似的东西,它已经包含了导入。您可以在此处查看文档:Ecto.Query.where docs.

[d] 是宏如何处理给要在 where 子句中使用的记录命名的方式。您可以将名称更改为任何名称,同时更改条件:

query
|> where([a_particular_record], a_particular_record.user_id == ^user.id)

请注意,该宏还覆盖了 ^ 的含义 - 在宏内部,它表示“从宏外部注入此值”,这就是为什么您需要在 user.id 之前使用它。

where 是一个接受查询作为第一个参数的宏,returns 是一个查询,因此它可以在管道中使用。管道化许多 where 会导致它们与 AND 组合。如果要将 where 子句与 OR 结合使用,可以使用 or_where 宏。

所以,下面的代码:

query
|> where([user], user.id == ^user.id)
|> where([user], user.name == ^user.name)

将生成如下所示的 SQL 查询:

WHERE user.id = 1 AND user.name = 'somename'

第二个参数是所谓的列表bindings。在上面的示例中,user 是一个绑定。绑定的工作方式很像 SQL 中的 table 别名,并有效地为您提供了一个变量,用于在整个查询过程中引用您的 table (此描述取自伟大的 Programming Ecto,它给出了深入了解 Ecto 的工作原理和使用方法)。绑定列表可以包含多个元素,以防查询包含连接。使用联接时,绑定应按照指定的顺序进行匹配。

from(user in User)
|> join(:inner, [user], user_settings in assoc(u, :user_settings))
|> where([_user, us], where: us.role == "admin")

绑定变量名称可以不同,但​​它们指向同一事物。在上面的示例中,join 中的用户设置绑定到 user_settings 变量,但在 where 子句中,它们绑定到 us 变量。

命名绑定也是可能的,它们可以解决一些非命名绑定无法解决的问题,但这里不做描述。更多关于他们的信息可以在 Ecto Documentation.

中找到

where 宏中的最后一个参数是一个必须计算为布尔值的表达式。此表达式包含您要编写的实际 where 子句。