如何在模式中嵌套两个graphQL查询?

时间:2017-10-25 09:54:39

标签: javascript graphql

我创建了一个带有两个字段的 GraphQLSchema ,两个字段都使用{ article(id: "Dn59y87PGhkJXpaiZ") { title }, articleContent(id: "Dn59y87PGhkJXpaiZ") { _id, content(language: "en"), type } } 从mongoDB获取数据。

有了这个,查询......

{
  "data": {
    "article": {
      "title": "Sample Article"
    },
    "articleContent": [
      {
        "_id": "Kho2N8yip3uWj7Cib",
        "content": "group",
        "type": "group"
      },
      {
        "_id": "mFopAj4jQQuGAJoAH",
        "content": "paragraph",
        "type": null
      }
    ]
  }
}

...导致:

{
  "data": {
    "article": {
      "title": "Sample Article",
      "content": [
        {
          "_id": "Kho2N8yip3uWj7Cib",
          "content": "group",
          "type": "group"
        },
        {
          "_id": "mFopAj4jQQuGAJoAH",
          "content": "paragraph",
          "type": null
        }
      ]
    },
  }
}

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

预期结果

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

对我来说,问题是异步mongoDB在我的架构中解析:

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

$con = new mysqli('localhost', 'root', 'root', 'purchases');
    if (!$con) {
        echo "Not connected to database";
    } else {
        $query = "INSERT INTO orders (Game, Price, Quantity, Total, fName, lName, Address, City, State, Zip, Email) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
$stmt = $con->prepare($query);
$stmt->bind_param("s", $game);
$stmt->bind_param("d", $price);
$stmt->bind_param("i", $qty);
$stmt->bind_param("d", $subtotal);
$stmt->bind_param("s", $fName);
$stmt->bind_param("s", $lName);
$stmt->bind_param("s", $address);
$stmt->bind_param("s", $state);
$stmt->bind_param("s", $zip);
$stmt->bind_param("s", $email);


        if ($stmt->execute() === TRUE) {
            echo "Inserted";
        } else {
            echo "Not Inserted";
        }
    }

1 个答案:

答案 0 :(得分:1)

首先,让我们分析一下解析器的签名。

function resolve(root, args, context)

root是父解析器返回的值。这就是为什么你得到Cannot read property 'collection' of undefined,因为父解析器没有返回一个db属性的对象。

args是传递给字段的参数,如下所示:article(id:'someid')在编写查询时。

context是传递给每个解析程序的参数,主要用于创建可访问的API范围的实用程序,例如db连接。

要在您的上下文中设置db,您可以使用它初始化GraphQL服务器。

app.use('/graphql', graphqlHTTP({
  schema: schema,
  rootValue: root,
  context: {
    db: db
  },
  graphiql: true,
}));

关于现在的嵌套,你可能会有这样的东西。

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

按顺序,这将会发生:

  • 文章获取其参数ID并将其返回给儿童解析器。

  • 标题和外部内容将同时触发其请求,访问db中的context

  • 当外部内容从db返回时,每个元素的内部内容字段将使用其参数language来返回正确的结果。