graphQL新手,我使用以下架构:
type Item { id: String,valueA: Float,valueB: Float } type Query { items(ids: [String]!): [Item] }
我的API可以在每种类型的单个请求(A& B)上返回多个项目,但不能同时返回两个项目,即:
对typeA的REST请求:api / a / items?id = [1,2]
响应:
[ {"id":1,"value":100},{"id":2,"value":30} ]
对typeB的REST请求:api / b / items?id = [1,"value":50},"value":20} ]
我想将这两个api端点合并到一个graphQL响应中,如下所示:
[ { id: "1",valueA: 100,valueB: 50 },{ id: "2",valueA: 30,valueB: 20 } ]
问:如何编写一个解析器,为每种类型运行一次获取(获取多项响应),确保在查询缺少类型时不会触发不必要的提取,即:
{items(ids:["1","2"]) { id valueA }}
上面的例子应该只获取api / a / items?id = [1,2]并且graphQL响应应该是:
[ { id: "1",valueA: 100 },valueA: 30 } ]
解决方法
所以我假设您使用JavaScript作为语言.在这种情况下,您需要的是不使用直接查询,而是使用片段
所以查询将成为
{ items(ids:["1","2"]) { ...data }} fragment data on Item { id valueA } }
接下来在解析器中,我们需要访问这些片段以查找作为片段一部分的字段,然后根据相同的数据解析数据.下面是一个简单的nodejs文件
const util = require('util'); var { graphql,buildSchema } = require('graphql'); var schema = buildSchema(` type Item { id: String,valueB: Float } type Query { items(ids: [String]!): [Item] } `); var root = { items: (source,args,root) => { var fields = root.fragments.data.selectionSet.selections.map(f => f.name.value); var ids = source["ids"]; var data = ids.map(id => {return {id: id}}); if (fields.indexOf("valueA") != -1) { // Query api/a/items?id=[ids] //append to data; console.log("calling API A") data[0]["valueA"] = 0.12; data[1]["valueA"] = 0.15; } if (fields.indexOf("valueB") != -1) { // Query api/b/items?id=[ids] //append to data; console.log("calling API B") data[0]["valueB"] = 0.10; data[1]["valueB"] = 0.11; } return data },}; graphql(schema,`{items(ids:["1","2"]) { ...data }} fragment data on Item { id valueA } `,root).then((response) => { console.log(util.inspect(response,{showHidden: false,depth: null})); });
如果我们运行它,输出是
calling API A { data: { items: [ { id: '1',valueA: 0.12 },{ id: '2',valueA: 0.15 } ] } }
如果我们将查询更改为
{ items(ids:["1","2"]) { ...data }} fragment data on Item { id valueA valueB } }
输出是
calling API A calling API B { data: { items: [ { id: '1',valueA: 0.12,valueB: 0.1 },valueA: 0.15,valueB: 0.11 } ] } }
因此,这演示了如何在不需要字段时避免调用api A / B.正如你所要求的那样