GraphQL – 返回计算types依赖于参数

概述 (简体):

在我的NodeJS服务器中,我已经实现了下面的GraphQL模式:

type Item { name: String, value: Float } type Query { items(names: [String]!): [Item] } 

客户端查询然后传递一个名称数组作为参数:

 { items(names: ["total","active"] ) { name value } } 

后端API查询一个mysql数据库,“ 总计 ”和“ 活动 ”字段(我的数据库表上的列),并减less响应,如下所示:

 [{"name":"total" , value:100} , {"name":"active" , value:50}] 

我想我的graphQL API支持“比例”项目,IE:我想发送以下查询:

 { items(names: ["ratio"] ) { name value } } 

要么

 { items(names: ["total","active","ratio"] ) { name value } } 

然后返回active / total作为新字段的计算结果( [{"name":"ratio" , value:0.5}] )。 什么是一个通用的方式来处理“ 比例 ”字段不同?

应该是我的模式中的新types,还是应该在reducer中实现逻辑?

Joe的答案(从数据库中获取结果后追加{"name":"ratio" , value:data.active/data.total} )将不做任何模式更改。

作为一种替代方法,或者作为在GraphQL中更好的方法,可以在types本身中指定字段名称,而不是将它们作为parameter passing。 并通过编写一个parsing器来计算ratio

所以,GraphQL模式将是:

 Item { total: Int, active: Int, ratio: Float } type Query { items: [Item] } 

客户端指定字段:

 { items { total active ratio } } 

并且可以在parsing器内计算ratio

这里是代码:

 const express = require('express'); const graphqlHTTP = require('express-graphql'); const { graphql } = require('graphql'); const { makeExecutableSchema } = require('graphql-tools'); const getFieldNames = require('graphql-list-fields'); const typeDefs = ` type Item { total: Int, active: Int, ratio: Float } type Query { items: [Item] } `; const resolvers = { Query: { items(obj, args, context, info) { const fields = getFieldNames(info) // get the array of field names specified by the client return context.db.getItems(fields) } }, Item: { ratio: (obj) => obj.active / obj.total // resolver for finding ratio } }; const schema = makeExecutableSchema({ typeDefs, resolvers }); const db = { getItems: (fields) => // table.select(fields) [{total: 10, active: 5},{total: 5, active: 5},{total: 15, active: 5}] // dummy data } graphql( schema, `query{ items{ total, active, ratio } }`, {}, // rootValue { db } // context ).then(data => console.log(JSON.stringify(data))) 

你可以设置你的parsing器函数,所以它使用第二个参数 – 参数 – 来查看名称“比例”是否在你的名字数组中:

 resolve: (root, { names }, context, fieldASTs) => { let arrayOfItems; // Contact DB, populate arrayOfItems with your total / active items // if 'ratio' is within your name array argument, calculate it: if (names.indexOf("ratio") > -1){ // Calculate ratio arrayOfItems.push({ name: "ratio", value: calculatedRatio }); } return(arrayOfItems); } 

我希望我正确理解你的问题