7

我在尝试扩展我的 API 以包含 GraphQL 端点时遇到了问题。我正在开发的应用程序是一种带有Messages. 消息可以包含类型的注释Message。如果消息是评论,则它的父类型为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       
              }
            }       
          }
        }   
      }
    }
  }
}

请记住,我可能希望允许任意深度嵌套评论。在这种情况下,应该允许以下查询:

{
  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]
}
4

3 回答 3

4

以防万一其他人在这里想知道如何在 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

于 2015-11-26T03:13:07.447 回答
0

我想你有一个数据结构的depth属性Comment,它应该非常有用,例如,当用户发表评论时限制最大嵌套深度。

这样您的问题就可以这样解决:在resolver属性comments中,检查depth,如果 非法,则不返回任何内容depth,否则获取评论并返回。

于 2015-09-10T09:35:05.247 回答
0

如果一条消息是一条评论,它有一个消息类型的父级。

看起来该parent字段应该在type Comment,而不是DefaultMessage。这仍然不会阻止parent - comments - parent查询,但是如果您出于 DDOS 原因担心这一点,那么即使使用 REST API,还有许多其他类型的请求难以计算,您应该采取其他措施来检测此类攻击.

递归节点

但是,您对嵌套评论提出了一个非常有趣的问题。你怎么知道你需要comment在查询中嵌套多少次才能获得所有嵌套的响应?我认为 GraphQL 目前无法指定递归对象。

我可能会绕过这个限制,从最后一条评论开始,逐个(或一次按 X 级)获取每个嵌套评论作为node

{
  messages {
    comments {
      id
      content
    }
  }
}

其次是

{
  node(commendId) {
    comment {
      id
      content
    }
  }
}
于 2015-09-10T09:03:30.537 回答