使用 Ecto.Query 查询具有 UUID 的 table 给出 Ecto.Query.CastError

Querying a table with UUID using Ecto.Query gives Ecto.Query.CastError

所以我进行了以下迁移:

create table(:things, primary_key: false) do
  add :id, :uuid, primary_key: true
  add :state, :string

  timestamps()
end

具有以下架构:

@primary_key {:id, Ecto.UUID, autogenerate: true}
@derive {Phoenix.Param, key: :id}
schema "things" do
  field :state, :string

  timestamps()
end

在 REPL 中尝试以下查询后,我得到一个 Ecto.Query.CastError:

iex(8)> q = from s in Thing, where: s.id == "ba34d9a0-889f-4999-ac23-f04c7183f2ba", select: s
#Ecto.Query<from o in App.Thing,
 where: o.id == "ba34d9a0-889f-4999-ac23-f04c7183f2ba", select: o>
iex(9)> Repo.get!(Thing, q)
** (Ecto.Query.CastError) /project/deps/ecto/lib/ecto/repo/queryable.ex:341: value `#Ecto.Query<from o in App.Thing, where: o.id == "ba34d9a0-889f-4999-ac23-f04c7183f2ba", select: o>` in `where` cannot be cast to type Ecto.UUID in query:

from o in App.Thing,
  where: o.id == ^#Ecto.Query<from o in App.Thing, where: o.id == "ba34d9a0-889f-4999-ac23-f04c7183f2ba", select: o>,
  select: o

    (elixir) lib/enum.ex:1811: Enum."-reduce/3-lists^foldl/2-0-"/3
    (elixir) lib/enum.ex:1357: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3
    (elixir) lib/enum.ex:1811: Enum."-reduce/3-lists^foldl/2-0-"/3
    (ecto) lib/ecto/repo/queryable.ex:124: Ecto.Repo.Queryable.execute/5
    (ecto) lib/ecto/repo/queryable.ex:37: Ecto.Repo.Queryable.all/4
    (ecto) lib/ecto/repo/queryable.ex:78: Ecto.Repo.Queryable.one!/4
    (stdlib) erl_eval.erl:670: :erl_eval.do_apply/6
    (iex) lib/iex/evaluator.ex:219: IEx.Evaluator.handle_eval/5
    (iex) lib/iex/evaluator.ex:200: IEx.Evaluator.do_eval/3
    (iex) lib/iex/evaluator.ex:178: IEx.Evaluator.eval/3

我不确定这是将 UUID 与 Ecto 一起使用的正确方法,我环顾四周,但有几个人的做法不同。我在 postgrex.

中使用 Ecto 2.1 和 Postgres 10.0

关于如何让 Ecto 正确查询和转换 UUID 的任何提示?

编辑:我在查询中提供的 ID 是我从数据库中复制的实际现有 ID。

我发现您遇到的问题一开始有点令人困惑,但我认为它工作得很好 - 问题在于您查询数据库的方式。

如果您已准备好查询,则需要使用 Repo.all(query),因此您的代码应为:

q = from s in Thing, where: s.id == "ba34d9a0-889f-4999-ac23-f04c7183f2ba", select: s
Repo.all(q)

可以通过主键查询数据库查找特定的记录,此时可以使用Repo.get!/3.

试试这个:

Repo.get!(Thing, "ba34d9a0-889f-4999-ac23-f04c7183f2ba")

当您将 q 作为第二个参数传递给 get! 时,它会尝试将其转换为 UUID,但实际上,查询不是 cast-able,在异常中解释为:

** (Ecto.Query.CastError) /project/deps/ecto/lib/ecto/repo/queryable.ex:341: value `#Ecto.Query<from o in App.Thing, where: o.id == "ba34d9a0-889f-4999-ac23-f04c7183f2ba", select: o>` in `where` cannot be cast to type Ecto.UUID in query:

你能看到整个 #Ecto.Query<> 都包含在 `` 中吗?

您可以在文档中找到更多信息:

希望对您有所帮助!