Elixir,Ecto 模式匹配条件与数据库查询不符合预期

Elixir, Ecto pattern matching conditional with db query not behaving as expected

如果记录不存在,我希望这个条件可以创建它,但它没有....返回 nil。

case Repo.get_by(User, %{email: "hulk@hogan.com"}) do
    struct ->
      struct
    nil ->
      params = Map.merge(%{email: "hulk@hogan.com"}, %{password: "password"})
      Repo.insert!(User.changeset(User.__struct__, params))
end

# returns nil.... huwutt???

但是,如果我更改条件的顺序,它就会起作用。我在这里错过了什么?

case Repo.get_by(User, %{email: "hulk@hogan.com"}) do
    nil ->
      params = Map.merge(%{email: "hulk@hogan.com"}, %{password: "password"})
      Repo.insert!(User.changeset(User.__struct__, params))
    struct ->
      struct
end

# returns a set of 24" pythons, brother.... huzah!

根据 documentation

case allows us to compare a value against many patterns until we find a matching one:

换句话说,第一个匹配的案例将运行和case不会继续进行。

在您的第一个示例中,第一种情况将始终匹配,因为您没有提供任何守卫,因此,struct 将绑定到 nil。您的第二种方法解决了这个问题,因为您首先对特定案例进行模式匹配,然后通过将 case 的评估绑定到 struct.

默认为一般案例

另请注意,您可以在第一种情况下使用守卫来确保 struct 的值是 map,如 here 所述。

case Repo.get_by(User, %{email: "hulk@hogan.com"}) do
    struct when is_map(struct) ->
      struct
    nil ->
      params = Map.merge(%{email: "hulk@hogan.com"}, %{password: "password"})
      Repo.insert!(User.changeset(User.__struct__, params))
end