构建 GraphQL 类型
Posted
技术标签:
【中文标题】构建 GraphQL 类型【英文标题】:Structuring GraphQL types 【发布时间】:2015-12-03 06:05:59 【问题描述】:我在尝试扩展我的 API 以包含 GraphQL 端点时遇到了问题。我正在开发的应用程序是一种Messages
的论坛。消息可以包含 Message
类型的 cmets。如果消息是评论,则它的父级类型为Message
。简化后,架构如下所示:
type Message
id: String
content: String
comments: [Message]
parent: Message
type RootQuery
message(id: String): Message
messages: [Message]
这个模式的问题是它允许这样的查询:
messages
comments
parent
comments
parent
comments
parent
id
content
请记住,我可能希望允许任意深度的 cmets 嵌套。在这种情况下,应该允许以下查询:
messages
comments
comments
comments
id
content
所以,我的问题是:我是否应该向不知道其父级的 API 引入一种新类型 - 注释?或者有没有其他方法可以限制这种不受欢迎的行为?
另外,评论类型的使用会禁止我在查询中使用fragment messageFields on Message
语法吗?也许现在是时候为模式引入接口了?
如果我引入类型 Comment 的解决方案建议(我没有尝试过):
interface Message
id: String
content: String
comments: [Message]
type DefaultMessage : Message
id: String
content: String
comments: [Comment]
parent: Message
type Comment : Message
id: String
content: String
comments: [Message]
type RootQuery
message(id: String): Message
messages: [Message]
【问题讨论】:
【参考方案1】:以防万一其他人在这里想知道如何在 graphql-js 中执行递归类型,graphql-js 的代码中有一个有用的提示:
* When two types need to refer to each other, or a type needs to refer to
* itself in a field, you can use a function expression (aka a closure or a
* thunk) to supply the fields lazily.
*
* Example:
*
* var PersonType = new GraphQLObjectType(
* name: 'Person',
* fields: () => (
* name: type: GraphQLString ,
* bestFriend: type: PersonType ,
* )
* );
*
*/
https://github.com/graphql/graphql-js/blob/master/src/type/definition.js#L274
【讨论】:
【参考方案2】:如果消息是评论,则它有一个消息类型的父级。
看起来parent
字段应该在type Comment
下,而不是DefaultMessage
。这仍然不会阻止parent - comments - parent
查询,但如果您出于 DDOS 原因担心这一点,那么即使使用 REST API,还有许多其他类型的请求难以计算,您应该有其他措施来检测这样的攻击。
递归节点
但是,您对嵌套 cmets 提出了一个非常有趣的问题。您怎么知道需要在查询中嵌套comment
多少次才能获得所有嵌套响应?我认为 GraphQL 目前无法指定递归对象。
我可能会绕过这个限制,从作为node
的最后一条评论开始逐个(或一次按 X 层)获取每个嵌套评论
messages
comments
id
content
紧随其后
node(commendId)
comment
id
content
【讨论】:
【参考方案3】:我想你有 Comment
数据结构的 depth
属性,它应该非常有用,例如,当用户发布 cmets 时限制最大嵌套深度。
这样您的问题可以这样解决:在comments
属性的resolver
中,检查depth
,如果depth
非法,则不返回任何内容,否则获取cmets 并返回。
【讨论】:
以上是关于构建 GraphQL 类型的主要内容,如果未能解决你的问题,请参考以下文章
构建时出现 TypeScript 错误,因为我导入提取的 .graphql 文件并且无法解析类型