node.js - GraphQL API 中的清洁架构和实体延迟加载
问题描述
我正在尽我的能力和理解力尝试按照清洁架构原则改进现有项目的架构,但我正在努力解决的问题之一是在 GQL 解析器中适合延迟加载实体的位置。
如果我们考虑拥有一个 Product 实体的示例,该实体在一对多类型的关系中与它相关联的类别(在我的应用程序中,它的 MTM,但为了简单起见,让我们继续吧),那么对应的 Product 类型看起来和这个相似
type Category {
name: String!
...
}
type Product {
...
name: String
description: String
categories: [Category!]!
}
客户可以查询表中的任何 Product 字段,products
如果他需要访问与该产品关联的类别,他可以使用该categories
字段。
为了避免过度获取,正确的做法似乎是最初仅从表中获取数据,如果客户端要求,则products
有条件地从表中加载数据。categories
因此,要解析类别,我们需要有条件地查询categories
表。
据我所知,我可以使用存储库模式来获取Product
域对象并将其返回给 GrapQL 查询解析器。
但是,我不明白的是,查询附加实体的逻辑应该在哪里?
例如,如果Product
域对象有一个方法,那么我可以loadCategories
从解析器调用它Categories
const resolvers = {
Product: {
async categories(product, args, ctx) {
return product.loadCategories()
}
}
}
但是,这将要求 Product 对象依赖于Repository
DAO 或另一个 DAO,据我所知,我不应该这样做。
我是否Repository
在graphql的对象中注入一个或一个DAO context
,并使用解析器中的那个?
这个似乎我会以一种方式倒退,但以另一种方式 - 不是那么多。因为根查询解析器有点像控制器,因此可以使用存储库。但是这个嵌套字段解析器在某种程度上属于Product
域对象,我觉得这有点令人困惑。
另外,如果我有一个授权策略,比如说,它允许来宾用户阅读name
产品的内容,而不是(如果他们无法阅读,description
我应该返回),那么该逻辑应该存在于哪里?null
解决方案
存储库或 [可能是外部的] 数据源通过上下文传递...
'父',第一个解析器arg是一个[通常]普通对象,具有解析数据属性(fe product.id)[通常]当前解析器需要[过滤/SQL where] ...
'父'(在这种情况下为产品)解析器可以返回带有字段/道具的对象......但您可以返回超过响应所需的内容......其中一个可以是带有 [lazy] 的 [lazy] 初始化(Product
实体)实例getCategories()
] getter ...但拥有自己的存储库访问权限?不使用 ctx 传递的存储库/数据源?或在“补水”期间注射...
...这个吸气剂应该返回什么?只有身份证?ACL -null
在某些情况下?(使用上下文中的用户?)......它应该是一个极简数组{id, name/title}
还是完整的类别条目?再次......这是一个Category
解析器[-s]角色
会不会太复杂?也许适合一些业务逻辑/字段/道具?
字段的 ACL?解析器角色,也是
任何 [type] 解析器都可以使用存储库……它是一个图表……不仅适用于根解析器……这将是紧密耦合/依赖关系。
推荐阅读
- api - API 附加 id,
- unity3d - 将 Minecraft 角色与皮肤一起使用到统一游戏中
- python - 机器人 - 如何继续失败,但使用 python 脚本而不是关键字突出显示报告中的失败
- sql - Spring boot JPA - 数据库中实体的主键
- symfony - 在 foreach 中使用 formBuilder 生成多个字段
- r - ggplot增加轴标签和轴刻度之间的距离
- google-sheets - 谷歌表格公式删除所有标点符号,不包括句点 (.)
- javascript - 如何在哈希模式下使用 Vue 路由器查询参数?
- mongodb - 如何在 Golang 中为 mongo DB $match 创建动态 bson
- javascript - 用于最终下拉填充的信息数组的“正确”JSON 格式