我正在Phoenix框架之上构建一个Elixir应用程序,该应用程序具有从Spotify API收集数据并将其持久保存到PostgreSQL 9.4数据库以便快速访问的功能。我在更新使用embeds_many
的现有表行时遇到问题。
我有Track和AlbumArt Ecto模型,如下所示:
defmodule CoolApp.Track do
use CoolApp.Web, :model
alias CoolApp.AlbumArt
alias CoolApp.Repo
alias CoolApp.Track
schema "tracks" do
field :sid, :string
field :title, :string
field :artist, :string
field :artist_sid, :string
field :album, :string
field :album_sid, :string
field :sort_order, :integer
field :is_now_playing, :boolean
# embeds_many :album_art, AlbumArt
# added on_replace: :delete
embeds_many :album_art, AlbumArt, on_replace: :delete
timestamps
end
end
defmodule CoolApp.AlbumArt do
use CoolApp.Web, :model
embedded_schema do
field :width, :integer
field :height, :integer
field :url, :string
end
end
*_sid
字段是spotify ID。嵌入式album_art
列是一个数据数组,如:
{
"height": 600,
"width": 600,
"url": "https://....."
}
我要做的是通过API响应,规范化数据以匹配我的架构,然后遍历它并在数据库中更新它。我所使用的代码适用于插入,但在更新时完全失败:
def persist_track(track_params, sort_order) do
album_art_params = transform_json_album_art_params(track_params.album_art)
track_params =
track_params
|> Map.delete(:album_art)
|> Map.put(:sort_order, sort_order)
try do
Repo.get_by!(Track, sid: track_params.sid)
|> Track.changeset(track_params)
|> Ecto.Changeset.put_change(:album_art, album_art_params)
|> Repo.update!
rescue
Ecto.NoResultsError ->
Track.changeset(%Track{}, track_params)
|> Ecto.Changeset.put_change(:album_art, album_art_params)
|> Repo.insert!
error ->
raise error
end
end
我通过并更新每个主要内容的原因主要是刷新数据,但如果更改了sort_order
,也会更新。{/ p>
当代码运行时,对于更新,我会回来:
** (RuntimeError) you are attempting to change relation :album_art of
CoolApp.Track, but there is missing data.
By default, if the parent model contains N children, at least the same
N children must be given on update. In other words, it is not possible
to orphan embed nor associated records, attempting to do so results
in this error message.
It is possible to change this behaviour by setting :on_replace when
defining the relation. See `Ecto.Changeset`'s section on related models
for more info.
我已经阅读了一些关于:on_replace
设置的内容,并尝试了:delete
,但无济于事。我只想每次使用新设置来破坏该列。这有可能吗?
编辑:我回到git历史记录并试图重新创建我的情况,并发现看到:on_replace
到:delete
实际上确实解决了问题。因为我没有承诺我所处的确切情况,所以我不能100%确定我是否错过了其他一些小问题。我必须养成一个习惯,在这里更好地抓住我的状态。