【问题标题】:Filesystem (file, folder) with display order具有显示顺序的文件系统(文件、文件夹)
【发布时间】:2017-01-07 11:56:23
【问题描述】:

我想设计像os文件系统, 可以更新具有特定显示顺序(顺序)的。

我希望文件和文件夹可以在同一层, 文件不必在文件夹中。 但是在下面的设计中,如果文件不在任何文件夹中,我不知道如何保存序列,保存在哪里?

任何建议都会受到重视

数据示例

folder(id:1)      top layer: sequence: 0
  file(id:1)                 sequence_in_folder: 0
  file(id:2)                 sequence_in_folder: 1
folder(id:2)      top layer: sequence: 1
  file(id:3)                 sequence_in_folder: 0
file(id:4)        top layer: sequence: 2 << **sequence save in which table ??**
file(id:5)        top layer: sequence: 3 << **sequence save in which table ??**

folder
id  sequence  parent_folder_id
1   0
2   1

file
id  sequence_in_folder  folder_id
1   0                   1
2   1                   1
3   0                   2
4   ?????
5   ????

架构

CREATE TABLE IF NOT EXISTS "folder"(
  "id" SERIAL NOT NULL,
  "sequence" integer NOT NULL,
  "parent_folder_id" integer Default NULL,
  PRIMARY KEY ("id")
);

CREATE TABLE IF NOT EXISTS "file"(
  "id" SERIAL NOT NULL,
  "sequence_in_folder" integer Default NULL,
  "parent_folder_id" integer NOT NULL,
  PRIMARY KEY ("id")
);

更新
基于@Laurenz Albe 的回答,无需更改表格设计, 只需创建一个根文件夹。
但是如何通过两个表中的交叉/存在字段对数据顺序进行排序? 文件夹表和文件表中存在序列,如何排序在一起

查询

SELECT * FROM folder fo 
  LEFT JOIN file fi ON fi.parent_folder_id = fo.id
WHERE fo.parent_folder_id = $1 AND fi.parent_folder_id = $1
  ORDER BY  fo.sequence fi.sequence ??   ;

[1]

数据示例

folder
id | sequence | parent_folder_id | name
1  | 0        |                  | root
2  | 0        | 1                | 
3  | 2        | 1                |

file
id | sequence | parent_folder_id |
1  | 1        | 1                |

输出

folder(id:1, sequence:0 name:root)
  folder(id:2, sequence:0)
  file(id:1, sequence:1)
  folder(id:3 sequence:2)

【问题讨论】:

  • 序列有什么问题?
  • @ChrisTravers 这个设计似乎只适用于bookmark 必须在bookmark_folder 中 bookmark.sequence = 特定文件夹中的序列

标签: database postgresql database-design relational-database


【解决方案1】:

两个建议:

  1. 引入一个包含所有顶级元素的“匿名”顶级文件夹。

  2. bookmerk_foldersequence列重命名为max_sequence左右,以免与bookmark.sequence混淆。

【讨论】:

  • 感谢您的回复,我无法解决我的问题,您能提供一些示例代码吗?
  • 嗯,有一个“根”folder,例如带有id = 0 的那个。那是包含顶级项目的那个。每当您向folder 添加新元素时,都会将folder.max_sequence 增加一并将该数字用作file.sequence
  • ...对不起,我不明白。你的意思是我必须先创建一个根文件夹保存在文件夹表中然后..
  • 对。这符合现实,不是吗?
【解决方案2】:

补充 Laurenz 的回答:

统一您的书签和文件夹列,可能是书签节点,并要求所有内容都有一个不是书签的父项。类似的东西

CREATE TABLE IF NOT EXISTS fsnode(
  "id" SERIAL NOT NULL,
  "name" text,
  "is_folder" bool,
  "parent_is_folder" bool not null,
  "sequence" integer NOT NULL,
  "parent_folder_id" integer Default NULL,
  CHECK (parent_is_folder),
  PRIMARY KEY ("id"),
  UNIQUE(id, is_folder), # needed for fkey below
  FOREIGN KEY (parent_folder_id, parent_is_folder) REFERENCES fsnode (id, is_folder)
);

【讨论】:

  • 谢谢回复,你的意思是只有一张桌子吗?如果 parent_folder_id fk id ,根文件夹仍然可以是空值吗? CHECK (parent_is_folder) 是什么意思如果parent_is_folder == false 不接受插入??
  • 对,所有行都必须将 parent_is_folder 设置为 true。但是 parent_folder_id 的外键仍然可以为空。那是为了防止书签也成为文件夹。
  • 如果parent_folder_id 可以为null 也可以在引用中是否意味着如果我想删除,只需执行delete from .. where id = .. 之类的操作,所有子相关行将自动递归删除,不需要使用这个jsfiddle.net/L934gyo7 递归查询?
  • 您可以通过在 DELETE CASCADE 上设置外键来做到这一点,但这是一个单独的讨论。
  • 我明白了,我会用这个,非常感谢!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多