如何在架构中嵌套两个graphQL查询? [英] How to nest two graphQL queries in a schema?
问题描述
我已经创建了一个具有两个字段的 GraphQLSchema ,都使用 resolve()
从mongoDB中获取数据.
I've created a GraphQLSchema with two fields, both using a resolve()
to get the data from a mongoDB.
有了这个,查询...
With that, the query...
{
article(id: "Dn59y87PGhkJXpaiZ") {
title
},
articleContent(id: "Dn59y87PGhkJXpaiZ") {
_id,
content(language: "en"),
type
}
}
...导致:
{
"data": {
"article": {
"title": "Sample Article"
},
"articleContent": [
{
"_id": "Kho2N8yip3uWj7Cib",
"content": "group",
"type": "group"
},
{
"_id": "mFopAj4jQQuGAJoAH",
"content": "paragraph",
"type": null
}
]
}
}
但是我需要一个这样的结果结构(内容应该在article对象的内部):
But I need a result structure like this (content should be inside of article object):
预期结果
{
"data": {
"article": {
"title": "Sample Article",
"content": [
{
"_id": "Kho2N8yip3uWj7Cib",
"content": "group",
"type": "group"
},
{
"_id": "mFopAj4jQQuGAJoAH",
"content": "paragraph",
"type": null
}
]
},
}
}
对我来说,问题都是我的架构中的异步mongoDB解决了:
For me the problem are both async mongoDB resolves in my schema:
export default new GraphQLSchema({
query: new GraphQLObjectType({
name: 'RootQueryType',
fields: {
article: {
type: new GraphQLObjectType({
name: 'article',
fields: {
title: {
type: GraphQLString,
resolve (parent) {
return parent.title
}
}
}
}),
args: {
id: { type: new GraphQLNonNull(GraphQLID) }
},
async resolve ({ db }, { id }) {
return db.collection('content').findOne({ _id: id })
}
},
articleContent: {
type: new GraphQLList(new GraphQLObjectType({
name: 'articleContent',
fields: {
_id: { type: GraphQLID },
type: { type: GraphQLString },
content: {
type: GraphQLString,
args: {
language: { type: new GraphQLNonNull(GraphQLString) }
},
resolve (parent, { language }, context) {
return parent.content[language][0].content
}
}
}
})),
args: {
id: { type: new GraphQLNonNull(GraphQLID) }
},
async resolve ({ db }, { id }) {
return db.collection('content').find({ main: id }).toArray()
}
}
}
})
})
更新
如果我将内容嵌套在文章中,则会收到错误消息无法读取未定义的属性'collection'
If I nest the content inside the article, I do get the error Cannot read property 'collection' of undefined
export default new GraphQLSchema({
query: new GraphQLObjectType({
name: 'RootQueryType',
fields: {
article: {
type: new GraphQLObjectType({
name: 'article',
fields: {
title: {
type: GraphQLString,
resolve (parent) {
return parent.title
}
},
articleContent: {
type: new GraphQLList(new GraphQLObjectType({
name: 'articleContent',
fields: {
_id: { type: GraphQLID },
type: { type: GraphQLString },
content: {
type: GraphQLString,
args: {
language: { type: new GraphQLNonNull(GraphQLString) }
},
resolve (parent, { language }, context) {
return parent.content[language][0].content
}
}
}
})),
args: {
id: { type: new GraphQLNonNull(GraphQLID) }
},
async resolve ({ db }, { id }) { // db is undefined here!!
return db.collection('content').find({ main: id }).toArray()
}
}
}
}),
args: {
id: { type: new GraphQLNonNull(GraphQLID) }
},
async resolve ({ db }, { id }) {
return db.collection('content').findOne({ _id: id })
}
}
}
})
})
推荐答案
首先,让我们分析解析器的签名.
First, let's analyze the signature of a resolver.
function resolve(root, args, context)
root
是父解析器返回的值.这就是为什么您得到无法读取未定义属性'collection'的原因
,因为父解析器未返回具有 db
属性的对象.
root
is the value returned by the parent resolver. This is why you get Cannot read property 'collection' of undefined
because the parent resolver didn't return an object with a db
property.
args
是传递给该字段的参数,例如:编写查询时, article(id:'someid')
.
args
are the argument passed to the field, like so: article(id:'someid')
when writing the query.
context
是传递给每个解析器的参数,主要用于使可访问API的实用程序,例如您的 db
连接.
context
is a parameter that is passed to every resolver, and is mostly used to make accessible API-wide utilities, like your db
connection.
要在上下文中设置 db
,可以使用它初始化GraphQL服务器.
To have db
set inside your context, you can initialize your GraphQL server with it.
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: root,
context: {
db: db
},
graphiql: true,
}));
关于现在的嵌套,您可能会遇到这样的事情.
About the nesting now, you could have something like this.
export default new GraphQLSchema({
query: new GraphQLObjectType({
name: 'RootQueryType',
fields: {
article: {
args: {
id: { type: new GraphQLNonNull(GraphQLID) }
},
resolve (_, { id }) {
return id; // will make it accessible to children resolvers
}
type: new GraphQLObjectType({
name: 'article',
fields: {
title: {
async resolve (id /* resolved by article */, _, { db } /* db from context */) {
const article = await db.collection('content').findOne({ _id: id });
return article.title;
}
type: GraphQLString,
},
content: {
async resolve (id /* resolved by article */, _, { db } /* db from context */) {
const contents = await db.collection('content').find({ main: id }).toArray();
return contents;
}
type: new GraphQLList(new GraphQLObjectType({
name: 'articleContent',
fields: {
_id: { type: GraphQLID },
type: { type: GraphQLString },
content: {
args: {
language: { type: new GraphQLNonNull(GraphQLString) }
},
aync resolve (parent /* resolved in content */, { language }) {
return parent.content[language][0].content
}
type: GraphQLString,
}
}
})),
}
}
}),
}
}
})
})
依次发生,这将发生:
-
article获取其参数id并将其返回,并将其提供给子解析器.
article gets its parameter id and returns it, giving it to children resolvers.
标题和外部内容都将并行触发其请求,并在 context
中访问 db
.
title and outer content will both fire their request in parallel, accessing the db
in context
.
当外部内容从数据库返回时,每个元素的内部内容字段将使用其参数 language
返回正确的结果.
when outer content gets back from the db, the inner content field of every element will use their parameter language
to return the right result.
这篇关于如何在架构中嵌套两个graphQL查询?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!