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

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

问题描述

我创建了一个带有两个字段的 GraphQLSchema,都使用 resolve() 从 mongoDB 中获取数据.

I've created a GraphQLSchema with two fields, both using a resolve() to get the data from a mongoDB.

这样,查询...

{
  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
      }
    ]
  }
}

但我需要这样的结果结构(内容应该在文章对象内):

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()
        }
      }
    }
  })
})

<小时>

更新

如果我将内容嵌套在文章中,我会收到错误 Cannot read property 'collection' of undefined

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 是父解析器返回的值.这就是为什么您得到 Cannot read property 'collection' of undefined 的原因,因为父解析器没有返回具有 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天全站免登陆