我有这些桌子
folders
和files
文件夹
schema "folders" do
field :name, :string
field :archived, :boolean
belongs_to :folder, Folder
has_many :folders, Folder
has_many :files, File
end
文件
schema "files" do
field :name, :string
field :archived, :boolean
belongs_to :folder, Folder
end
当我们软删除文件夹和文件时,会使用
archived
列。
父文件夹可以有无限的子文件夹和文件。
FolderA
|-file1
|-file2
|-folder_b
|-file1
|-folder_c
|-file1
|-folder_d
...
# NO_LIMIT
现在,我需要做的是,如果我软删除
FolderA
,所有子文件夹和文件也应该被软删除(将 archived
值更新为 true
)。
如何在 Ecto 甚至 PostgreSQL 中完成此操作?
我修改了 Ecto 文档中的示例(https://hexdocs.pm/ecto/Ecto.Query.html#with_cte/3-recursive-ctes)以满足您的需求:
def soft_delete_tree_for_folder(root_folder) do
root_id = root_folder.id
folder_tree_initial_query = where(Folder, [f], f.id == ^root_id)
folder_tree_recursion_query = join(Folder, :inner, [f], fo in "folders_tree", on: fo.folder_id == f.id)
folder_tree_query = union_all(folder_tree_initial_query, ^folder_tree_recursion_query)
Folder
|> recursive_ctes(true)
|> with_cte("folders_tree", as: ^folder_tree_query)
|> join(:left, [f], fo in "folders_tree", on: fo.id == f.folder_id)
|> group_by([f], f.id)
|> select([f, fo], f)
|> Repo.soft_delete_all()
end