Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Postgresql 设置Phoenix框架和Exto以使用UUID:如何插入生成的值?_Postgresql_Elixir_Phoenix Framework_Ecto - Fatal编程技术网

Postgresql 设置Phoenix框架和Exto以使用UUID:如何插入生成的值?

Postgresql 设置Phoenix框架和Exto以使用UUID:如何插入生成的值?,postgresql,elixir,phoenix-framework,ecto,Postgresql,Elixir,Phoenix Framework,Ecto,几天前,我开始在Postgres数据库中使用Elixir和Phoenix框架(V0.12.0)。我正在尝试创建一个具有UUID主键的表,我更喜欢它,而不是顺序默认值 在使用mix phoenix.gen.html生成模型和迁移文件并遵循phoenix文档中的其他步骤后,我已经改变了 def model do quote do use Ecto.Model end end 在web.ex中 def model do quote do use Ecto.

几天前,我开始在Postgres数据库中使用Elixir和Phoenix框架(V0.12.0)。我正在尝试创建一个具有UUID主键的表,我更喜欢它,而不是顺序默认值

在使用
mix phoenix.gen.html
生成模型和迁移文件并遵循phoenix文档中的其他步骤后,我已经改变了

def model do
    quote do
      use Ecto.Model
    end
  end
web.ex

def model do
  quote do
    use Ecto.Model
    @primary_key {:id, :uuid, []}
    @foreign_key_type :uuid
  end
end
正如在外太空文件中提到的。我还将迁移更改为

create table(:tblname, primary_key: false) do
  add :id, :uuid, primary_key: true
  [other columns]
end
不幸的是,当我试图从自动生成的表单向表中添加条目时,我得到了一个错误,因为
id
为空。如果我手动将
id
-列添加到模型中,我会收到一个错误,即该列已经存在。如果我在
table/2
中忽略将
primary\u键设置为false,并删除
id
列,则该表将生成一个顺序
id
-列


我需要在变更集中手动设置
id
,还是在设置我的应用程序以使用UUIDs时出错?提前感谢

编辑:我已将此答案更新为Ecto v2.0。你可以在最后阅读前面的答案

外星2型 从最初的答案开始,在EXTO中处理UUID变得更加直截了当。Ecto有两种类型的id:
:id
:binary\u id
。第一个是我们从数据库中知道的整数ID,第二个是特定于数据库的二进制文件。对于博士后来说,这是一个UUID

要将UUID作为主键,请首先在迁移中指定它们:

create table(:posts, primary_key: false) do
  add :id, :binary_id, primary_key: true
end
然后在模型模块中(在
模式
块之外):

当您为
:binary\u id
指定
:autogenerate
选项时,EXTO将保证适配器或数据库将为您生成它。但是,如果愿意,您仍然可以手动生成它。顺便说一句,您可以在迁移中使用
:uuid
,在模式中使用
exto.uuid
,而不是
:binary\u id
:binary\u id
的好处是它可以跨数据库移植

外胚层v1 您需要告诉数据库如何自动生成UUID。或者您需要从应用程序端生成一个。这取决于你喜欢哪一个

在我们继续之前,有一点很重要,那就是您使用的是
:uuid
,它将返回二进制文件,而不是人类可读的uuid。很可能您想要使用
exto.UUID
,它将把它格式化为字符串(aaaa-bbb-ccc-…),这就是我将在下面使用的内容

在数据库中生成 在迁移中,为字段定义默认值:

add :id, :uuid, primary_key: true, default: fragment("uuid_generate_v4()")
我假设您正在运行PostgreSQL。您需要使用pgAdmin中的
创建扩展“uuid ossp”
安装uuid ossp扩展,或者在迁移中添加
执行“创建扩展\”uuid ossp \
。有关的更多信息

回到EXTO,在您的模型中,要求EXTO在插入/更新后从数据库中读取字段:

@primary_key {:id, Ecto.UUID, read_after_writes: true}
现在,当您插入时,数据库将生成一个默认值,并且Ecto将读回该值

在应用程序中生成 您需要定义一个为您插入UUID的模块:

defmodule MyApp.UUID do
  def put_uuid(changeset) do
    Ecto.Changeset.put_change(changeset, :id, Ecto.UUID.generate())
  end
end
并将其用作回调:

def model do
  quote do
    use Ecto.Model
    @primary_key {:id, Ecto.UUID, []}
    @foreign_key_type Ecto.UUID
    before_insert MyApp.UUID, :put_uuid, []
  end
end
before\u insert
是一个回调函数,它将使用给定的参数调用给定函数中的给定模块,其中一个变更集表示要插入的内容作为第一个参数


就这些了。顺便说一句,将来这项工作可能会更加精简。:)

同样在创建新的项目过程选项时--binary-id
使用UUID作为默认主键。(启动exto v2


谢谢你的快速回复!不幸的是,这两种方法都会导致Postgrex出错。如果我在我的应用程序中生成UUID,我会收到以下错误:Postgrex.Extensions.Binary.encode/4中没有匹配的函数子句。如果我将exto.Changeset.put_new_change/3链接到模型中的管道以将UUID添加到参数中,我会收到相同的错误。如果我让Postgres通过调用UUID_generate_v4()来生成UUID,Postgrex会抱怨函数不存在:(Postgrex.Error)Error(undefined_函数):在pgAdmin
UUID_generate_v4()中执行
CREATE EXTENSION“UUID ossp”
后,函数UUID_generate_v4()不存在,该行已正确创建。但是,索引视图返回UnicodeConversionError。我不确定Postgres为什么抱怨
uuid\u generate\u v4()
。也许你需要安装一些模块?我不记得确切的步骤,所以我添加了一个指向文档的链接。其他错误是因为您在模型中使用了
:uuid
,而不是
exto.uuid
,我已经在第二段的后面部分解释了为什么要使用它。我还更新了代码示例,这样其他人就不会犯与我们相同的错误!感谢您的反馈。另一个重要的事情是将引用类型指定为uuid<代码>添加:post\u id,引用(:posts,type::uuid)
def model do
  quote do
    use Ecto.Model
    @primary_key {:id, Ecto.UUID, []}
    @foreign_key_type Ecto.UUID
    before_insert MyApp.UUID, :put_uuid, []
  end
end
mix phx.new project_name --binary-id