首页 > 解决方案 > 1-many 关系的前向访问通常是如何实现的?

问题描述

我了解一对多关系最容易由具有指向父项的外键引用的子项表示。

Parent
  - id

Child
  - id
  - parentId // fk

在这种情况下,从孩子访问父母是微不足道的。只需对父表进行 O(1) 访问。

但是如何管理一个父母的所有孩子的有效访问呢?

例如,像Parent.children()通常在 orm 中实现的方法如何才能高效?

我考虑过/尝试过的一些事情:

如果父级也有一个 列表childIds: [],这将起作用,但是您必须在创建后将 childId 插入到父级 childIds 中。创建模型的两个操作似乎是错误的,即使它让我们 O(1) 访问子 ID 列表。

您可以简单地循环遍历所有子children.filter(({ parentId }) => parentId === 2)项以获取此处的子项,例如,Parent 2 您想要访问所有 Parent 2 的子项的每条领带。但这是 O(n) 次操作,效率低下。

是否有一些标准方法可以避免这两个陷阱?即,实现以一对多关系返回父模型的子代的 orm 方法的标准方法是什么?

标签: javascriptorm

解决方案


根据@philipxy 的评论,最好的方法是回答我自己的问题,也许其他人可以更好地回答。

ORM 允许您声明关系和方法以获取相关实体查询的结果,但 ORM 执行的查询是特定于存储的,这就是它“更有效”的地方。在 SQL 存储中,开发人员通常不会考虑这一点,ORM 只会运行 eg select * from children where parentId = 2,并且存储会提高效率。

看来您有一个 javascript 对象存储。除非性能是一个真正的问题,否则 是children.filter({ parentId }) === parent.id使用的方法redux-orm,并且考虑到现代浏览器的速度很可能就足够了。

对于 SQL 存储,可能有更底层的方法来优化此类查询。例如,如果所有孩子都按 parentId 排序,则可以使用比 O(n) 更有效的算法。一些这样的方法也可以应用于 javascript 对象存储。

换句话说,在子模型上使用 parentId 会导致从 1 到 many 时出现过滤问题。

您还提到了这样一个事实,即您可以表示父级具有子级 ID 的一对多关系。鉴于在这种情况下,如果您想从一个孩子转到父母(找到其中一个孩子拥有您所追求的孩子 ID 的父母),您仍然会面临过滤问题,除非出于某种原因您打算非常频繁地从父母传给孩子,但反之亦然,这可能不太合适。它不太适合业务问题,即孩子在没有父母的情况下有意义地存在,例如对帖子的评论,因为以这种方式存储关系需要孩子首先存在。

简而言之,实现 1-many 方法的 O(n) 循环将需要较大的 n 成为性能瓶颈,如果是这样,还有其他小于 O(n) 的过滤方法。您可以探索 CS 过滤算法以进一步了解这一点。此外,如果您正在实施您的商店,许多选项都是有效的,这取决于您的具体情况。SQL 通常会在某种程度上抽象使用的算法,但如果您正在实现自己的商店,则需要根据您的案例更仔细地考虑这一点。


推荐阅读