使用返回元组的函数更新地图列表

时间:2019-02-10 22:56:33

标签: elixir phoenix-framework ecto

我正在使用Elixir 1.8.0和Ecto 3.0.7

我有一张看起来像这样的地图

things = [
  %{
    availability_zone: "us-west-1a",
    dns_name: "ec2-13-45-67-46.us-west-1.compute.amazonaws.com",
    image_id: "ami-251234",
    instance_id: "i-1234",
    instance_state: "running",
    instance_type: "m4.large",
    ip_address: "13.45.67.46",
    key_name: "some_key",
    launch_time: "2018-06-13T16:34:04.000Z",
    monitoring: "disabled",
    private_ip_address: "10.1.1.1",
    vpc_id: "vpc-9999"
  },
  %{
    availability_zone: "us-west-1a",
    dns_name: "ec2-13-99-99-46.us-west-1.compute.amazonaws.com",
    image_id: "ami-2522344",
    instance_id: "i-99999",
    instance_state: "running",
    instance_type: "m4.large",
    ip_address: "13.99.99.99",
    key_name: "some_key",
    launch_time: "2018-06-13T16:34:04.000Z",
    monitoring: "disabled",
    private_ip_address: "10.1.1.2",
    vpc_id: "vpc-9999"
  }
]

我正在尝试使用Ecto.Repo.insert_all将此列表插入到我的数据库中。这不能按原样工作,因为我正在将launch_time称为utc_datetime,而这不是我列表中的DateTime。

我正在尝试将其转换为DateTime,但是from_iso8601返回一个元组,这当然是行不通的。

iex(12)> things |> Enum.map(fn elem ->
...(12)>         Map.update!(elem, :launch_time, &DateTime.from_iso8601/1)
...(12)>       end)
[
  %{
    availability_zone: "us-west-1a",
    dns_name: "ec2-13-56-179-46.us-west-1.compute.amazonaws.com",
    image_id: "ami-25110f45",
    instance_id: "i-0df401bc2d3b16d37",
    instance_state: "running",
    instance_type: "m4.large",
    ip_address: "13.56.179.46",
    key_name: "salt_provisioning",
    launch_time: {:ok, #DateTime<2018-06-13 16:34:04.000Z>, 0},
    monitoring: "disabled",
    private_ip_address: "10.81.1.244",
    vpc_id: "vpc-07a5e160"
  },
  %{
    availability_zone: "us-west-1a",
    dns_name: "ec2-13-56-179-46.us-west-1.compute.amazonaws.com",
    image_id: "ami-25110f45",
    instance_id: "i-0df401bc2d3b16d37",
    instance_state: "running",
    instance_type: "m4.large",
    ip_address: "13.56.179.46",
    key_name: "salt_provisioning",
    launch_time: {:ok, #DateTime<2018-06-13 16:34:04.000Z>, 0},
    monitoring: "disabled",
    private_ip_address: "10.81.1.244",
    vpc_id: "vpc-07a5e160"
  }
]

如何仅将DateTime取回管道,以便可以insert_all列表?还是需要多个步骤?

2 个答案:

答案 0 :(得分:1)

您可以对现有代码进行一些改动,希望它能满足您的要求:

>> ['family', 'famfor']

答案 1 :(得分:1)

虽然肯定可以Enum.map/2,但惯用且更灵活的方法是使用Access行为(Access.all/0用于列表,)和Kernel.get_and_update_in/3

get_and_update_in(things, [Access.all(), :launch_time], fn prev ->
  {prev, with {:ok, neu, _} <- DateTime.from_iso8601(prev), do: neu}
end) 

(或(prev |> DateTime.from_iso8601() |> elem(1))),如果所有输入数据均被证明有效。