跳至主要内容

pgPolymorphic

此步骤类只是在 @dataplan/pg 中支持多态性的众多方法之一;我们建议您在决定是否需要此步骤之前阅读 多态性 文档,因为它是最冗长的选项之一!可能更简单的方法更适合您。

pgPolymorphic 通过获取记录步骤(pgSelectSingle)、指定器步骤(任意步骤)和实体类型映射来工作。实体类型映射键是可能的 GraphQL 类型名称,对于这些名称中的每一个,其值都是一个具有以下属性的对象

  • match - 一个函数,它接受指定器数据并返回 true 如果它与该类型匹配
  • plan - 一个函数,它接收一个匹配规范的step规范和原始记录step,并应返回一个表示由该规范标识的记录的step。

示例

假设我们有一个数据库,您可以在其中从三个不同的表中收藏记录:“people”、“posts”和“comments”。

这些收藏存储在一个名为“favourites”的表中,该表除了其他属性(例如执行收藏操作的用户的ID)之外,还有三个属性来指示收藏了哪个实体:liked_person_idliked_post_idliked_comment_id。这三个属性实现了“one of”模式 - 这三个属性中只有一个会被设置,其他属性为null。

我们希望根据代表“favourites”表中行的step $favourite,检索您收藏的实体。

利用上述知识,我们可以构建一个规范step $specifier,它包含所有必要的数据来确定我们希望检索的多态记录,方法是将三个“one of”ID表示为元组(或列表)。

const $specifier = list([
$favourite.get("liked_person_id"),
$favourite.get("liked_post_id"),
$favourite.get("liked_comment_id"),
]);

我们基于此规范准备我们的 personFavouriteEntityTypeMap 匹配器,它查看元组并确定

  • 如果元组中的第一个条目(与 liked_person_id 关联的条目)不为null,则该记录必须表示一个 Person,并且我们可以从 personResource 中获取相关的person,其中 person_id 等于元组中的第一个条目
  • 否则,如果第二个条目不为null,则该记录必须表示一个 Post,并且我们可以以类似的方式从 postResource 中获取该post
  • 否则,如果第三个条目不为null,则该记录必须表示一个 Comment,并且我们可以以类似的方式获取该comment
const personFavouriteEntityTypeMap = {
Person: {
match: (specifier) => specifier[0] != null,
plan: ($specifier) => personResource.get({ person_id: $specifier.at(0) }),
},
Post: {
match: (specifier) => specifier[1] != null,
plan: ($specifier) => postResource.get({ post_id: $specifier.at(1) }),
},
Comment: {
match: (specifier) => specifier[2] != null,
plan: ($specifier) => commentResource.get({ comment_id: $specifier.at(2) }),
},
};

最后,我们将我们的记录step($favourite)、规范step($specifier)和匹配器(personFavouriteEntityTypeMap)传递给 pgPolymorphic,它将知道如何检索关联的记录 - person、post或comment

return pgPolymorphic($favourite, $specifier, personFavouriteEntityTypeMap);