我正在重新实现我最初在Phoenix中用Rails编写的一个应用程序,在这个应用程序中,用户可以使用PostgreSQL的JSONB记录类型创建自定义字段。作为一个例子,我们有以下(简化表示)模式:
客户- ID (int)
- 客户端类型ID (int)
- 名称(字符串)
- 信息(jsonb)
- ID (int)
- 名称(字符串)
自定义字段定义
- ID (int)
- 客户端类型ID (int)
- 键(字符串)
- 标签(字符串)
在Rails中,ActiveRecord神奇地将JSONB转换为散列,这允许我使用JSONB非常容易地存储一组无模式的自定义字段。
例如,每种客户机类型可以定义不同的自定义字段,然后当我向用户显示信息时,我循环遍历定义以获取键,然后使用键从JSONB文档中获取数据。
我试图找出一种方法来完成这个使用Ecto,它看起来像我应该看一个嵌入式模式(我在这里看到了一些很好的信息),但是我不认为从看它,我可以在运行时定义自定义字段的数量,我可以吗?
我只是在寻找一些建议,因为到目前为止,这是我遇到的唯一一个没有立即解决的真正障碍。
再次感谢,我很感激!
我可以通过稍微改变我的数据结构来解决这个问题。自定义字段现在是一个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
Postgrex在其自述文件中有一个JSON扩展的示例,它应该完全符合您的要求。