无法查询类型 \"Mutation\" 上的字段 \"addWorkout\"

Posted

技术标签:

【中文标题】无法查询类型 \\"Mutation\\" 上的字段 \\"addWorkout\\"【英文标题】:Cannot query field \"addWorkout\" on type \"Mutation\无法查询类型 \"Mutation\" 上的字段 \"addWorkout\" 【发布时间】:2020-05-31 16:00:21 【问题描述】:

我对 GraphQL 相当陌生,我之前的问题是关于我得到的一些参考错误,我最终解决了,但是,现在我得到了这个错误。似乎我无法添加锻炼,因为它无法识别它是模式中的突变字段。

我不断收到错误

Cannot query field \"addWorkout\" on type \"Mutation\

无论如何,在 app.js 上,这是我的代码

const express = require("express")
const app = express();
const userSchema = require("./graph-schema/userQueries")
const workoutSchema = require("./graph-schema/workoutQueries")
const mealSchema = require("./graph-schema/mealQueries")
const mongoose = require("mongoose")
const mergeSchemas = require("graphql-tools")

//connect to mongoDB atlase database
mongoose.connect("mongodb+srv://Zubair97:superman2008@cluster0-epauj.mongodb.net/test?retryWrites=true&w=majority")
mongoose.connection.once("open", () => 
    console.log("Connected to database")
)

const combinedSchemas = mergeSchemas(
    schemas: [
        userSchema,
        mealSchema,
        workoutSchema
    ],
)




//this module allows express to communicate with graphql ;
//we use it as a single endpoint
const graphqlHTTP = require("express-graphql")

app.use("/graphql" , graphqlHTTP(
    schema: combinedSchemas,
    graphiql: true


))


app.listen(4000, () => 
    console.log(`Listening on port 4000`)
)

锻炼查询和突变在我导出的一个名为锻炼查询.js 的文件中定义,您可以看到我在解析器中定义了 addWorkout

const graphql = require("graphql")
const WorkoutType = require("./schema")
const Workout = require("../models/Workout.js")
const GraphQLObjectType, GraphQLID, GraphQLString, GraphQLSchema, GraphQLInt, GraphQLList = graphql;

const WorkoutQuery = new GraphQLObjectType(
    name: "WorkoutQuery",
    fields: () => (
        workout: 
            type: WorkoutType,
            args: id: type: GraphQLID,
            resolve(parent, args)
                //returns the workout instance from the database
                return Workout.findById(args.id)
            

        ,

        workouts: 
            type: new GraphQLList(WorkoutType),
            resolve(parent, args)
                //returns all workouts from the databse
                return Workout.find()
            
        
    )

)

const WorkoutMutation = new GraphQLObjectType(
    name: "WorkoutMutation",
    addWorkout: 
        type: WorkoutType,
        args: 
            name: type: GraphQLString,
            reps: type: GraphQLInt,
            sets: type: GraphQLInt,
            burnedCalories: type: GraphQLInt,
            userId: type: GraphQLID,

        ,
        resolve(parent, args)
            let workout = new Workout(
                name: args.name,
                reps: args.reps,
                sets: args.sets,
                burnedCalories: args.burnedCalories,
                userId: args.userId
            )

            return workout.save();
        
    ,

)

module.exports = new GraphQLSchema(
    query: WorkoutQuery,
    mutation: WorkoutMutation
)

此外,即使我尝试添加餐点,也会出现此问题,查询和突变是在我已导出的名为 mealQueries.js 的文件中定义的

const graphql = require("graphql")
const MealType, NutritionType = require("./schema")
const Meal = require("../models/Meal.js")
const GraphQLObjectType, GraphQLID, GraphQLString, GraphQLSchema, GraphQLInt, GraphQLList = graphql;

const MealQuery = new GraphQLObjectType(
    name: "MealQueries",
    fields: () => (
        meal: 
            type: MealType,
            args: id: type: GraphQLID,
            resolve(parent, args)
                return Meal.findById(args.id)
            
        ,

        meals: 
            type: new GraphQLList(MealType),
            resolve(parent, args)
                return Meal.find()
            
        

    )

)

const MealMutation = new GraphQLObjectType(
    name: "MealMutation",
    addMeal: 
        type: MealType,
        args: 
            name: type: GraphQLString,
            servings: type: GraphQLInt,
            calories: type: GraphQLInt,
            nutrition: type: NutritionType,
            userId: type: GraphQLID
        ,
        resolve(parent, args)

            let meal = new Meal(
                userId: args.userId,
                name: args.name,
                servings: args.servings,
                calories: args.calories,
                nutrition: 
                    carbohydrates: args.nutrition.carbohydrates,
                    fats: args.nutrition.fats,
                    proteins: args.nutrition.proteins
                
            )

            return meal.save();
        
    

)

module.exports = new GraphQLSchema(
    query: MealQuery,
    mutation: MealMutation
)

我在创建用户和验证用户方面没有问题,在 userQueries.js 中定义的查询和突变

const graphql = require("graphql")
const User = require("../models/User.js")
const bcrypt = require("bcrypt")
const jwt = require("jsonwebtoken")
const AuthType, UserType = require("./schema")
const GraphQLObjectType, GraphQLID, GraphQLString, GraphQLSchema, GraphQLInt, GraphQLList = graphql;


const UserQuery = new GraphQLObjectType(
    name: "UserQuery",
    fields: () => (
        user: 
            type: UserType,
            args: id: type: GraphQLID,
            resolve(parent, args)
                //returns the user from the database
                return User.findById(args.id)
            
        ,
        login: 
            type: AuthType,
            args: email: type: GraphQLString, password: type: GraphQLString,
            resolve(parent, email, password)
                return User.findOne(email: email).then((user) => 
                    const isEqual = bcrypt.compare(password, user.password)
                    if (!isEqual) 
                        throw new Error('Password is incorrect!');
                    

                    const token = jwt.sign(
                        userId: user.id,
                        email: user.email,
                        "a_super_secret",
                        expiresIn: "1h"
                    )

                    return token: token, userId: user.id


                )

            
        


    )


)



const UserMutation = new GraphQLObjectType(
    name: "Mutation",
    fields: 
        addUser: 
            type: UserType,
            args: 
                name: type: GraphQLString,
                email: type: GraphQLString,
                password: type: GraphQLString
            ,
            async resolve(parent, args)
                const existingUser =  await User.findOne(email: args.email)
                if (!existingUser)
                    const error = new Error("User already exists");
                

                const encryptedPassword =  await bcrypt.hash(args.password, 12)

                let user = new User(
                    name: args.name,
                    email: args.email,
                    password: encryptedPassword
                )

                const createdUser =  user.save();
                return createdUser
            
        



    
)


module.exports = new GraphQLSchema(
    query: UserQuery,
    mutation: UserMutation,
)

我还在一个名为 schema.js 的文件中定义了 UserType、AuthType、MealType、NutritionType 和 WorkoutType

const graphql = require("graphql")
const Workout = require("../models/Workout.js")
const User = require("../models/User.js")
const Meal = require("../models/Meal")

const GraphQLObjectType, GraphQLID, GraphQLString, GraphQLSchema, GraphQLInt, GraphQLList = graphql;

//describes what attributes and its types, a User has in each query
const UserType = new GraphQLObjectType(
    name: "User",
    fields: () => (
        id: type: GraphQLID,
        name: type: GraphQLString,
        email: type: GraphQLString,
        password: type: GraphQLString,
        workouts: 
            type: new GraphQLList(WorkoutType),
            resolve(parent, args)
                //returns all the workouts created by a user
                return Workout.findById(userId: parent.id)
            
        ,
        meals: 
            type: new GraphQLList(MealType),
            resolve(parent, args)
                //returns all the meals created by a user
                return Meal.findById(userId: parent.id)
            
        

    )
)

const NutritionType = new GraphQLObjectType(
    name: "Nutrition",
    fields: () => (
        carbohydrates: type: GraphQLInt,
        fats: type: GraphQLInt,
        proteins: type: GraphQLInt
    )
)



const WorkoutType = new GraphQLObjectType(
    name: "Workout",
    fields: () => (
        id: type: GraphQLID,
        name: type: GraphQLString,
        reps: type: GraphQLInt,
        burnedCalories: type: GraphQLInt,
        sets: type: GraphQLInt,
        user: 
            type: UserType,
            resolve(parent, args)
                //returns the user from the database that created the workout instance
                return User.findById(parent.userId)

            
        

    )
)




const AuthType = new GraphQLObjectType(
    name: "Authentication",
    fields: () => (
        token: type: GraphQLString,
        userId: type: GraphQLString
    )
)



const MealType = new GraphQLObjectType(
    name: "Meal",
    fields: () => (
        id: type: GraphQLID,
        calories: type: GraphQLInt,
        servings: type: GraphQLInt,
        nutrition: type: NutritionType,
        user: 
            type: UserType,
            resolve(parent, args)
                //returns the user from the database that created the meal instance
                return User.findById(parent.userId)
            
        

    )
)




module.exports = 
    AuthType,
    WorkoutType,
    UserType,
    MealType,
    NutritionType

我怀疑我得到的错误是由于来自 graphql-tools 的 mergeSchema 对象,也许它无法正确合并 GraphQLSchema 类型?我不知道。任何帮助表示赞赏!

【问题讨论】:

我不知道 GraphQL,但只是看看你的代码,我想知道这是否是你的语法问题 - 请注意 UserQuery 它是 UserQuery.fields().addUser 但在你的 WorkoutMutation 你是跳过fields 并且只有WorkoutMutation.addWorkout - 我怀疑您需要添加fields()-> 包装器 【参考方案1】:

mergeSchemas 旨在与schema stitching 一起使用。它不应该仅仅用于模块化你的单一模式,这是你在这里尝试做的。

您应该只为您的查询根类型创建一个 GraphQLSchema 对象、一个 GraphQLObjectType 并为您的突变根类型创建一个 GraphQLObjectType。如果您希望特定类型的字段(例如 Mutation 类型)分布在多个模块中,那么您应该仅导出这些字段,而不是整个类型或架构。

module.exports = 
  queries: 
    workout:  ... ,
    workouts:  ... ,
  ,
  mutations: 
    addWorkout:  ... ,
  ,

您在其中创建架构的任何文件都可以从多个模块中导入这些字段并将它们组合成一个单独的架构。

const query = new GraphQLObjectType(
  name: 'Query',
  fields: () => (
    ...require('moduleA').queries,
    ...require('moduleB').queries,
    ...require('moduleC').queries,
  ),
)
const mutation = new GraphQLObjectType( ... )
const schema = new GraphQLSchema( query, mutation )

【讨论】:

以上是关于无法查询类型 \"Mutation\" 上的字段 \"addWorkout\"的主要内容,如果未能解决你的问题,请参考以下文章

紧跟在查询类型(query/mutation)GraphQL之后的字符串的意义

Angular Apollo:错误:GraphQL 错误:“Mutation”类型的字段“AuthLogin”上的未知参数“用户名”

具有“自定义类型”属性的DynamoDB表的Graphql Mutation查询

使用 Apollo Client 和 Apollo Server 的 React Native 应用程序的 Mutation 类型的未知参数“”on field“”

自定义输入类型的 Apollo 数组作为 Mutation 参数抛出“__typename”:未知字段错误

如何修复由数据类型关系引起的“变量“$_v0_data”得到无效值' - Mutation Resolver