【问题标题】:Delete orphaned records with Ecto使用 Ecto 删除孤立记录
【发布时间】:2020-05-10 07:46:02
【问题描述】:

我有 3 个模型:

user.ex

  schema "users" do 
    ...
    many_to_many(:acts, Act, join_through: UserAct)
  end

act.ex

  schema "acts" do
    ...
    many_to_many(:users, User, join_through: UserAct)
  end

user_act.ex

  schema "users_acts" do
    belongs_to :user, User
    belongs_to :act, Act
  end

每次我删除 UserAct 时,我想检查是否存在孤立的 Act 模型并在事务中删除它们。

在 SQL 中是这样的

DELETE FROM acts WHERE NOT EXISTS (
  SELECT 1 FROM users_acts ua WHERE ua.act_id = acts.id
);

or 

DELETE FROM acts WHERE id NOT IN (SELECT act_id FROM users_acts);

我的问题是如何用 Ecto 编写类似的查询?

请展示所有你知道的方法:joins、fragments 等...

【问题讨论】:

  • 为什么不在你的迁移中使用 on_delete: delete_all ?
  • @script on_delete 会在删除 parent 时删除所有子记录,例如删除 act,则删除所有引用的 user_act。当没有引用 user_acts 时,OP 想要删除行为。如果我错了,请纠正我。
  • @AbhyuditJain 你是对的。

标签: postgresql elixir phoenix-framework ecto


【解决方案1】:

一种解决方案是使用片段。

Repo.delete_all(
  from a in Act,
  where: fragment("? NOT IN (SELECT act_id FROM users_acts)", a.id)
)

【讨论】:

    【解决方案2】:

    使用连接:

    orphaned_query = Act
    |> join(:left, [a], a in assoc(a, :users))
    |> where([a, u], is_nil(u.id))
    
    Act
    |> join(:inner, [a], a in subquery(orphaned_query))
    |> Repo.delete_all()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-09-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-07
      • 2015-03-13
      • 2014-08-06
      相关资源
      最近更新 更多