GraphQL模式之间的共享结构

GraphQL模式之间的共享结构,graphql,relay,graphql-js,apollo,react-apollo,Graphql,Relay,Graphql Js,Apollo,React Apollo,我有一个Apollo GraphQL服务器,它与一个返回响应的API对话,其结构大致如下: { "pagination": { "page": 1, // more stuff }, sorting: { // even more stuff }, data: [ // Actual data ] } 这个结构将在我广泛使用的这个API的几乎所有响应中共享。数据在大多数情况下都是数组,但也可以是对象 我怎样才能高效地编写它,这样就不必在模式中的每种数

我有一个Apollo GraphQL服务器,它与一个返回响应的API对话,其结构大致如下:

{
  "pagination": {
    "page": 1,
    // more stuff
  },
  sorting: {
    // even more stuff
  },
  data: [ // Actual data ]
}
这个结构将在我广泛使用的这个API的几乎所有响应中共享。数据在大多数情况下都是数组,但也可以是对象

我怎样才能高效地编写它,这样就不必在模式中的每种数据类型上重复所有这些分页和排序字段


非常感谢

定义模式时,最终将分页、排序等抽象为单独的类型。因此,模式将类似于:

type Bar {
  pagination: Pagination
  sorting: SortingOptions
  data: BarData # I'm an object
}
type Foo {
  pagination: Pagination
  sorting: SortingOptions
  data: [FooData] # I'm an array
}
# more types similar to above
type Pagination {
  page: Int
  # more fields
}
type SortingOptions {
  # more fields
}
type BarData {
  # more fields
}
因此,您不必多次列出分页中的每个字段。但是,每种使用分页的类型仍然需要将其指定为一个字段——这是无法逃避的要求

或者,您可以设置一个用于所有对象的单一类型。在这种情况下,数据字段将是一个接口数据,FooData、BarData等都实现了它。在数据解析程序中,您可以定义一个_resolveType函数来确定返回哪种类型的数据。您可以在查询中传入typename变量,然后在_resolveType函数中使用该变量返回正确的类型

您可以在中看到一个很好的接口示例


后一种方法的缺点是,您必须返回单个数据对象或它们的数组—您不能混合和匹配—因此您可能必须更改返回对象的结构以使其工作。

我通过创建一个名为的库来解决您的问题。它通过添加对类型继承、泛型类型和元数据的支持来增强模式。在您的情况下,为分页对象创建泛型类型可能是一个可行的解决方案。以下是一个例子:

const { transpileSchema } = require('graphql-s2s')
const { makeExecutableSchema } = require('graphql-tools')

const schema = `
type Paged<T> {
    data: [T]
    cursor: ID
}
type Node {
    id: ID!
    creationDate: String
}
type Person inherits Node {
    firstname: String!
    middlename: String
    lastname: String!
    age: Int!
    gender: String 
}
type Teacher inherits Person {
    title: String!
}
type Student inherits Person {
    nickname: String!
    questions: Paged<Question>
}
type Question inherits Node {
    name: String!
    text: String!
}
type Query {

  students: Paged<Student>

  teachers: Paged<Teacher>
}
`

const executableSchema = makeExecutableSchema({
  typeDefs: [transpileSchema(schema)],
  resolvers: resolver
})

我在第二部分中详细介绍了这一点。

感谢您抽出时间。事实上,我以前想过这两种方法,但第一种方法迫使我每次重复排序和分页,还迫使我为每种类型创建一个Foo和一个FooData,这是非常丑陋和痛苦的。尽管如此,这仍然是我要使用的解决方案,因为第二个解决方案将迫使我编写一个非常庞大的resolveType函数,考虑到我拥有的所有不同类型。我在寻找第三条路,我想没有。这有点牵强,但你可以像这样研究。写出一个对象数组,只为每个对象指定数据字段。然后使用reduce插入排序和分页字段,并将数组转换为对象。这可能会更容易/更简短地编写,但我认为生成的模式可能也不如您当前的方法可读。我遇到了同样的挑战,我通过创建一个名为graphql-s2s的库进行了分类,该库允许增强您的模式以支持继承和泛型类型。请看一下本文的第二部分,其中我将介绍如何解决这个问题: