GraphQL 如何在子字段级别启用基于 ID 的查询?

How can GraphQL enable an ID based query at sub fields level?

如果现有服务分别支持以下 GraphQL 查询:

查询到某人的银行账户:

query {
    balance(id: "1") {
      checking
      saving
    }
}

结果

{
  "data": {
    "balance": {
      "checking": "800",
      "saving": "3000"
    }
  }
}

查询到某人的挂单:

query {
    pending_order(id: "1") {
      books
      tickets
    }
}

结果

{
  "data": {
    "pending_order": {
      "books": "5",
      "tickets": "2"
    }
  }
}

实现上述功能的源代码是这样的:

module.exports = new GraphQLObjectType({
  name: 'Query',
  description: 'Queries individual fields by ID',

  fields: () => ({
    balance: {
      type: BalanceType,
      description: 'Get balance',
      args: {
        id: {
          description: 'id of the person',
          type: GraphQLString
        }
      },
      resolve: (root, { id }) => getBalance(id)
    },
    pending_order: {
      type: OrderType,
      description: 'Get the pending orders',
      args: {
        id: {
          description: 'id of the person',
          type: GraphQLString
        }
      },
      resolve: (root, { id }) => getPendingOrders(id)
    }
  })
});

现在,我想让我的 GraphQL 服务模式支持个人级别模式,即

query {
    person (id: "1") {
      balance
      pending_order
    }
}

得到如下结果:

{
  "data": {
     "balance": {
       "checking": "800",
       "saving": "3000"
    }
    "pending_order": {
      "books": "5",
      "tickets": "2"
    }
  }
}

如何重构架构,如何重用现有的查询服务?

编辑(阅读 Daniel Rearden 的回答后)

我们能否优化 GraphQL 服务,以便我们根据查询进行服务调用?即,如果传入查询是

query {
    person (id: "1") {
      pending_order
    }
}

我的实际查询变成了

person: {
  ...
  resolve: (root, { id }) => Promise.all([
    getBalance(id)
  ]) => ({ balance})
}

您将必须定义一个单独的 Person 类型来包装 balancepending_order 字段。

module.exports = new GraphQLObjectType({
  name: 'Person',
  fields: () => ({
    balance: {
      type: BalanceType,
      resolve: ({ id }) => getBalance(id)
    },
    pending_order: {
      type: OrderType,
      resolve: ({ id }) => getPendingOrders(id)
    }
  })
});

并且您需要在 Query 类型中添加一个新字段:

person: {
  type: PersonType,
  args: {
    id: {
      type: GraphQLString
    }
  },
  // We just need to return an object with the id, the resolvers for
  // our Person type fields will do the result
  resolve: (root, { id }) => ({ id })
}

要让事情变得更干并重用现有代码,您无能为力。如果您正在寻找减少样板文件的方法,我建议 using graphql-tools.