首页 文章

构建GraphQL类型

提问于
浏览
4

我工作的是've run into an issue while trying to extend my API to include a GraphQL endpoint. The application I'是一种有 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引入新类型 - 注释吗?或者有没有其他方法来限制这种不受欢迎的行为?

另外,使用Comment类型会禁止我在查询中使用 fragment messageFields on Message 语法吗?也许现在是将接口引入模式的时候了?

如果我介绍类型注释(我还没试过这个),建议解决方案:

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

3 回答

  • 0

    为了防止其他人在这里想知道如何在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

  • 0

    如果消息是注释,则其父类型为Message .

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

    递归节点

    但是,您使用嵌套注释提出了一个非常有趣的问题 . 您如何知道在查询中嵌套 comment 以获取所有嵌套响应需要多少次?我目前无法使用GraphQL来指定递归对象 .

    我可能会通过从最后一个注释开始逐个获取每个嵌套注释(或者一次获取X个级别)来解决这个限制 node

    {
      messages {
        comments {
          id
          content
        }
      }
    }
    

    其次是

    {
      node(commendId) {
        comment {
          id
          content
        }
      }
    }
    
  • 3

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

    这样你的问题可以这样解决:在 comments 属性的 resolver 中,检查 depth ,如果 depth 非法,则不返回任何内容,否则返回注释并返回 .

相关问题