我正在重新实现我最初在Phoenix的Rails中编写的应用程序,用户可以使用PostgreSQL的
JSONB记录类型创建自定义字段.作为示例,我们具有以下(简化表示)模式:
客户
> ID(int)
>客户端类型ID(int)
>名称(字符串)
>信息(jsonb)
客户类型
> ID(int)
>名称(字符串)
自定义字段定义
> ID(int)
>客户端类型ID(int)
>键(字符串)
>标签(字符串)
在Rails中,ActiveRecord神奇地将JSONB转换为散列和从散列转换,这使我可以非常轻松地使用JSONB来存储无模式的自定义字段集.
例如,每个客户端类型可以定义不同的自定义字段,然后当我向用户显示信息时,我遍历定义以获取密钥,然后我将其用于从JSONB文档中获取数据.
我试图找到一种使用Ecto来实现这一目标的方法,看起来我应该看一个嵌入式架构(我看到了一些好的信息here),但我不认为从看它我可以定义一个我可以在运行时自定义字段数量吗?
我只是在寻找一些关于此的建议,因为到目前为止,这是我遇到的唯一真正的障碍,几乎没有立即解决.
再次感谢,我很感激!
最佳答案 我能够通过改变我的数据结构来解决这个问题.自定义字段现在是一个JSONB数组,它允许我进行非常优雅的embeds_many关系.我实际上还没有仔细阅读链接(
http://blog.plataformatec.com.br/2015/08/working-with-ecto-associations-and-embeds/)上的文档,在我做完之后我意识到我的数据不够结构化.
因此,而不是看起来像JSONB列
{
"name":"Something",
"address":"123 Fake St"
}
看起来像
[
{
"field":"name",
"value":"Something"
},
{
"field":"address",
"value":"123 Fake St"
},
]
这似乎是我的用例的最佳选择,但它确实占用了更多的空间(因为Ecto在幕后为每个对象添加了一个必需的ID字段以确保完整性).
更改为此结构后,我只是创建了一个模型并根据链接关联它们.简而言之,它看起来像这样:
defmodule UserManager.CustomField do
use Ecto.Model
embedded_schema do
field :field
field :value
end
@required_fields ~w(field value)
@optional_fields ~w()
@doc """
Creates a changeset based on the `model` and `params`.
If no params are provided, an invalid changeset is returned
with no validation performed.
"""
def changeset(model, params \\ :empty) do
model |> cast(params, @required_fields, @optional_fields)
end
end
defmodule UserManager.Client do
# ...
schema "clients" do
# ...
embeds_many :custom_fields, UserManager.CustomField
# ...
end
# ...
end