ecto jsonb array 和 map cast 问题
ecto jsonb array and map cast issue
我想使用可以是数组或地图的 jsonb 存储数据。源数据以数组或映射的形式到达,我们希望在服务器上统一它,以便前端可以使用单一类型。是否有我可以使用、存储和检索对 jsonb postgres 类型有效的 json/map 和数组类型的 way/workaround?
如果我在 params
:
中得到一个数组,我在调用 cast 管道之前尝试使用 source:
复制到数组类型 sourced
字段
condition: Map.has_key?(params, "value") && is_list(value)
我能够成功地保存数据,但是当从数据库中检索时我遇到了转换错误
field(:value, :map)
field(:value_array, {:array, :integer}, source: :value)
注意:Ecto 版本 > 3 和 postgres 10
解决方案是定义 custom ecto types 来接受和加载数组和映射
defmodule HaiData.Jsonb do
@behaviour Ecto.Type
def type, do: :map
# Provide custom casting rules.
def cast(data) when is_list(data) or is_map(data) do
{:ok, data}
end
# Everything else is a failure though
def cast(_), do: :error
# When loading data from the database, we are guaranteed to
# receive a map or list
def load(data) when is_list(data) or is_map(data) do
{:ok, data}
end
# When dumping data to the database, we *expect* a map or list
# so we need to guard against them.
def dump(data) when is_list(data) or is_map(data), do: {:ok, data}
def dump(_), do: :error
end
我想使用可以是数组或地图的 jsonb 存储数据。源数据以数组或映射的形式到达,我们希望在服务器上统一它,以便前端可以使用单一类型。是否有我可以使用、存储和检索对 jsonb postgres 类型有效的 json/map 和数组类型的 way/workaround?
如果我在 params
:
source:
复制到数组类型 sourced
字段
condition: Map.has_key?(params, "value") && is_list(value)
我能够成功地保存数据,但是当从数据库中检索时我遇到了转换错误
field(:value, :map)
field(:value_array, {:array, :integer}, source: :value)
注意:Ecto 版本 > 3 和 postgres 10
解决方案是定义 custom ecto types 来接受和加载数组和映射
defmodule HaiData.Jsonb do
@behaviour Ecto.Type
def type, do: :map
# Provide custom casting rules.
def cast(data) when is_list(data) or is_map(data) do
{:ok, data}
end
# Everything else is a failure though
def cast(_), do: :error
# When loading data from the database, we are guaranteed to
# receive a map or list
def load(data) when is_list(data) or is_map(data) do
{:ok, data}
end
# When dumping data to the database, we *expect* a map or list
# so we need to guard against them.
def dump(data) when is_list(data) or is_map(data), do: {:ok, data}
def dump(_), do: :error
end