我在节点中关注GraphQL的this教程。我已经完成了教程,但我现在正在扩展。
它是基于XML的goodreads API之上的GraphQL API。我很难与作者打交道,书中有作者有书等问题。
考虑以下两个GraphQLObjects:
const BookType = new GraphQLObjectType({
name: 'Book',
description: '...',
fields: () => ({
title: {
type: GraphQLString,
resolve: xml =>
xml.title[0]
},
isbn: {
type: GraphQLString,
resolve: xml =>
xml.isbn[0]
},
authors: {
type: GraphQLList(AuthorType2),
resolve: xml =>
xml.authors[0].author
}
})
});
const AuthorType = new GraphQLObjectType({
name: 'Author',
description: '...',
fields: () => ({
name: {
type: GraphQLString,
resolve: xml =>
xml.name[0]
},
books: {
type: GraphQLList(BookType),
// if author not inflated, this fails
resolve: xml => xml.books[0].book
}
//here could be another item that fails on uninflated authors
})
});
根API在/ author上提供了一个完全扩展的作者,以及书籍,而书籍又有一段作者数据(假设它只有id和名称)。
我的问题是如何将这位简化的作者扩展到完整的状态,包括书籍并解决这些问题。我在书中解析作者字段时无法做到这一点,因为用户可能只需要作者的名字,因此加载了不需要的数据。
在解析书籍时我也做不到,从那时起如果又增加了另一个需要膨胀状态的领域,就没有办法保存状态,所以每个作者必须发生两次通货膨胀。
有人可以解释一下吗?有没有办法在解析它的字段时改变AuthorType的状态?其他一些解决方法?谢谢!
答案 0 :(得分:0)
可能的解决方案是查看实际查询的字段。 resolve函数的第四个参数是较小的使用位,称为info
。在其中,您可以浏览针对特定字段查询的fieldNode树。
您可以在authors
字段解析功能中使用该信息来决定您是否要加载额外数据。类似的东西:
authors: {
type: GraphQLList(AuthorType),
resolve: (xml, args, context, info) => {
if (!info.fieldNodes[0].selectionSet.selections....) // It's a pretty robust structure
return xml.authors[0].author;
return loadAuthors(xml.title[0]) // However you load authors...
}
}
关于字段的类型。您可以查看GraphQL interface and union types。
答案 1 :(得分:0)
所以我一直在环顾四周,事实证明这不是解决这个问题的正确方法。最好使用某种类似于dataloader的每请求链接,并让每个需要额外端点的字段调用dataloader。这样,如果没有查询需要详细信息请求的字段,则不会进行第二次调用。此外,由于缓存,如果查询的多个字段需要详细调用,则只调用一次并缓存。
books: {
type: GraphQLList(BookType),
// if author not inflated, this fails
resolve: (obj, args, context) => {
return context.booksLoader.load(obj.id)
.then(obj => obj.books)
}
}
someOther: {
type: GraphQLList(BookType),
// if author not inflated, this fails
resolve: (obj, args, context) => {
return context.booksLoader.load(obj.id)
.then(obj => obj.someOther)
}
}