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

时间:2018-01-23 07:17:19

标签: graphql graphql-js express-graphql

如果现有服务分别支持以下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})
}

1 个答案:

答案 0 :(得分:1)

您将不得不定义单独的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