【发布时间】:2016-10-23 21:52:40
【问题描述】:
我想在 Postgres 中存储一个树结构,我希望在树的每个节点上嵌入一个任意 Elixir 结构,如下所示:
defmodule Node do
use Ecto.Schema
schema "nodes" do
belongs_to :parent_node, Node
embeds_one :struct, ArbitraryDataType
end
end
但是,我相信embeds_one 需要指定特定的结构数据类型,这不适用于我的情况。有没有办法解决这个问题?
我的备份计划是使用两个字段,一个用于结构type,一个用于结构fields,如下所示:
defmodule Node do
use Ecto.Schema
schema "nodes" do
belongs_to :parent_node, Node
field :struct_type, :string
field :fields, :map
end
end
为了首先保存记录,我需要使用__struct__ 字段来确定结构类型。然后,在从数据库中检索节点后,我将使用类似以下的逻辑来重建原始结构:
Enum.reduce(
retrieved_node.fields,
String.to_atom("Elixir.#{retrieved_node.struct_type}") |> struct,
fn {k,v}, s -> Map.put(s, String.to_atom(k), v) end
)
【问题讨论】:
-
为什么要存储
struct_type?结构基本上只是一个带有__struct__字段的映射。我会按原样存储它(作为一张普通的旧地图),你会得到ArbitraryDataType开箱即用。我错过了什么吗? -
我同意@mudasobwa。也许您想重新考虑首先存储
struct_type的设计决策。 -
这正是我希望做的,而且很可能有办法做到这一点。但是,当我将结构保存到 Postgres 中的 json 列时,Ecto 不会保留
__struct__键/值信息。因此,当我从数据库中检索该行时,我得到了一个“常规”旧地图,而不是我希望的结构 - type 信息丢失了。 -
您找到解决方案了吗?我也对使用任意结构以及能够持久化和查询并取回相同的结构感兴趣。我在此线程上发表了与您类似的问题的评论:elixirforum.com/t/…
-
还没有,虽然我太忙了,不能再做那个项目了。它可能会在架子上放一段时间……:/