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
Elixir 如何在EXTO模式中存储多维数组?_Elixir_Ecto - Fatal编程技术网

Elixir 如何在EXTO模式中存储多维数组?

Elixir 如何在EXTO模式中存储多维数组?,elixir,ecto,Elixir,Ecto,假设我希望将一组坐标([[x1,y1],[x2,y2]])存储到Postgres中。首选的数据类型是什么?文档允许以 :coordinates, {:array, :float} 但这只对一维数组有用。您可以使用 field :coordinates, {:array, {:array, :float}} 但这不是最好的解决方案。看起来很糟糕,允许将类似这样的内容插入到数据库中,这显然是不协调的。我更喜欢自定义类型 #lib/coordinates.ex defmodule Coordina

假设我希望将一组坐标(
[[x1,y1],[x2,y2]]
)存储到Postgres中。首选的数据类型是什么?文档允许以

:coordinates, {:array, :float}
但这只对一维数组有用。

您可以使用

field :coordinates, {:array, {:array, :float}}
但这不是最好的解决方案。看起来很糟糕,允许将类似这样的内容插入到数据库中,这显然是不协调的。我更喜欢自定义类型

#lib/coordinates.ex
defmodule Coordinates do
  @behaviour Ecto.Type

  def type, do: {:array, :float}

  def cast([l1, l2] = coordinates) when is_list(l1) and length(l1) == 2 and is_list(l2) and length(l2) == 2 do
    flattened_list = coordinates |> List.flatten

    cond do
      Enum.all?(flattened_list, &(is_float(&1))) ->
        {:ok, list}
      # add additional [integer, string, ...] to float transformations here if necessary
      # Enum.all?(flattened_list, &(is_float(&1) || is_integer(&1))) ->
      #   normalized = flattened_list |> Enum.map(&(&1 / 1)) |> Enum.split(2) |> Tuple.to_list
      #
      #   {:ok, normalized}
      true ->
        :error
    end
  end

  def cast(_), do: :error

  def load(list) when is_list(list) and length(list) == 4 do
    two_dimensional_list = list |> Enum.split(2) |> Tuple.to_list

    {:ok, two_dimensional_list}
  end

  def dump(list) when is_list(list) and length(list) == 2 do
    flattened_list = coordinates |> List.flatten

    {:ok, flattened_list}
  end

  def dump(_), do: :error
end

#web/models/your_model.ex
schema "your_model" do
  field :coordinates, Coordinates
end
根据文件,Exto.Type Behavior预计将实现4个功能

type应输出数据库类型的名称
cast应接收任何类型并输出您的自定义外部类型
load应接收DB类型并输出您的自定义EXTO类型
dump应该接收自定义的exto类型并输出DB类型

在上面的例子中,最重要的是转储和加载(一维和二维列表之间的转换)以及大量的保护(确保无效数据将返回:error)

我建议阅读完整的
exto.Type
docs:

这很有帮助。

谢谢。为了简单起见,最后使用迁移类型为
{:array,:float}
字段:坐标、{:array、{:array、:float}
。(列表可以是可变长度的,所以自定义类型代码会更复杂……而且期限很紧,哈哈。