pgPolymorphic
此步骤类只是在 @dataplan/pg
中支持多态性的众多方法之一;我们建议您在决定是否需要此步骤之前阅读 多态性 文档,因为它是最冗长的选项之一!可能更简单的方法更适合您。
pgPolymorphic 通过获取记录步骤(pgSelectSingle
)、指定器步骤(任意步骤)和实体类型映射来工作。实体类型映射键是可能的 GraphQL 类型名称,对于这些名称中的每一个,其值都是一个具有以下属性的对象
match
- 一个函数,它接受指定器数据并返回 true 如果它与该类型匹配plan
- 一个函数,它接收一个匹配规范的step规范和原始记录step,并应返回一个表示由该规范标识的记录的step。
示例
假设我们有一个数据库,您可以在其中从三个不同的表中收藏记录:“people”、“posts”和“comments”。
这些收藏存储在一个名为“favourites”的表中,该表除了其他属性(例如执行收藏操作的用户的ID)之外,还有三个属性来指示收藏了哪个实体:liked_person_id
、liked_post_id
、liked_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);