Phoenix Repo大量初始数据如何插入?

作者 dragonszy 所属板块 问答
假如我有数据格式如下,tab分割的.txt文件或者csv文件: ``` name buy sell 1 10 5 2 20 6 3 30 7 ``` 第一行对应了Struct的key名,后面行代表记录。 在Phoenix seeds.exs中插入的话需要使用Struct ``` Repo.insert!(%Record{name: 1, buy: 10, sell: 5}) ``` 有没有什么简便的方法读取并插入这种类型的数据啊?目前想到的方法就是正则处理一下转换成代码再插入。 还有,如果数据条目已存在,有没有简便的方法 upsert,比如这里name唯一,判断name是否存在,有没有什么简便方法? ``` Repo.get_by(Record, name: name) || Repo.insert!(%Record{name: 1, buy: 10, sell: 5}) ``` 有没有类似mongodb的 Repo.upsert 这样的函数?没有找到条目,则插入,找到条目,则更新。 刚开始学elixir和phoenix,很多东西只会用本办法做,请大家多多指教!
3 回复
  • tony612 发表
    Ecto 2 加入了 `Repo.insert_all`,可以看 http://blog.plataformatec.com.br/2016/05/ectos-insert_all-and-schemaless-queries/ 和 https://hexdocs.pm/ecto/2.0.1/Ecto.Repo.html#c:insert_all/3 name 的话,似乎没有更好的办法。不过如果你只是需要导数据的话,而且如果你数据量不大的话,完全可以在内存里判断咯。
  • dragonszy 发表
    [@tony612](/users/89) 学习了!试验一下!
  • dragonszy 发表
    ``` elixir iex(23)> data = ~w(1 10 5 ...(23)> 2 20 6 ...(23)> 3 30 7) # to list ["1", "10", "5", "2", "20", "6", "3", "30", "7"] data |> Enum.chunk(3) # to nested list key = ~w()a # to atom iex(25)> key = ~w(time buy sell)a [:time, :buy, :sell] for rec <- data do Enum.zip(key, rec) # add key |> Enum.into(%Record{}) # transfer to struct end Repo.insert(%Record{}) # single insert If not using `Eunm.into` to transfer to Struct, can use insert_all in ecto2 [[key, val, key, val], [key, val, key, val]] MyApp.Repo.insert_all(Post, [[title: "hello", body: "world"], [title: "another", body: "post"]]) # bulk insert ``` 写的有点乱,大体意思 1. ~w()a转换key 2. ~w()转换数据 3. Enum.chunk分组数据 4. Enum.zip添加key 5. Enum.into转换Struct后逐个插入Ecto 1.x 6. 批量 insert_all (Step4) Ecto 2.x