递归这种情况下的最优解?

Recursion the optimal solution in this case?

这让我很头疼。我正在构建一个系统,可以处理许多项目、组和文件引用。 请看看这个:

用户应该能够创建无限数量的项目、无限数量的组并附加无限数量的文件引用——就像普通的 PC 文件结构处理驱动器号、文件夹和文件一样。

所有提到的元素都驻留在 MySQL 数据库中。但是,我不确定这(见下文)是否是构建整个事物的最佳方式:

如您所见,它包含一个名为 "Xrefs" 的实体,包含项目和组。行指向自身内部,这可能使其成为检索数据时进行递归调用的理想选择。

一种不同的方法可能是为项目创建 1 个实体,为组创建 1 个实体,为文件引用创建 1 个实体...以及 1 个辅助实体,它将三个实体联系在一起,还包含 "parent" 值,(类似于第一个解决方案)引用上层元组以创建层次结构。

如果你要构建一个类似的项目,你会怎么做?

您的结构很好 - 因为您正在构建树,而不是一般图,所以不需要单独的 table 将实体联系在一起。我会将项目放入它们自己的 table,因为它们似乎独立存在,除非您还必须支持项目之间的层次结构。

但是,鉴于您的 RDBMS 是 MySQL,您在构建递归查询时会遇到问题。例如,尝试考虑一个查询,它会为您提供与 1xfer_id 相关的所有文件(即项目)。 None 的文件与该 ID 相关联,因此您需要找到您的第一级组,然后是您的第二级组,然后将文件绑定到它们。由于您的组可以嵌套在任意数量的级别中,因此您的查询也必须是递归的。

虽然你一定可以做到,it is currently not simple, and requires writing stored procedures。对于这种情况,一种常见的方法是在 RDBMS 的帮助下在内存中构建树。诀窍是在每个组中存储顶级项目的id,即

xfer_id xfer_fk xfer_top
------- ------- --------
    1      -       1
    2      1       1
    3      1       1
    4      3       1
    5      3       1

现在,带有条件 WHERE xfer_top=... 的查询将为您提供所有个体 "parts",它们可以在内存中组合,而无需将整个 table 放入内存。

您遇到了 MySQL 最著名的限制之一:使用所谓的递归查询 (PostgreSQL) 或 CTE 查询 (Oracle) 的能力。有一些可能的解决方法,但考虑到具有此类要求的项目,您可能会因许多其他众所周知的 MySQL 限制而遭受很多痛苦。在这个问题上,即使是 SQLLite 也会更有用(除了一个并发用户限制)。

DBIx::Class 有一些组件可以帮助您规避此 MySQL 限制,搜索 Nested TreesOrdered Trees 带递归查询[DBIx::Class::Tree::NestedSet][1]

您将需要对以下内容的支持:7.8. WITH Queries (Common Table Expressions),MySQL 不会为您提供。