如何在架构中嵌套两个graphQL查询? [英] How to nest two graphQL queries in a schema?

查看:76
本文介绍了如何在架构中嵌套两个graphQL查询?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经创建了一个具有两个字段的 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆