【问题标题】:Add Upload type to GraphQL将上传类型添加到 GraphQL
【发布时间】:2020-04-21 13:37:38
【问题描述】:

我正在尝试创建一个自定义解析器来为使用 composeWithMongoose 的 Express + Apollo Server + Mongoose 项目上传用户头像图像。

正在使用 SchemaComposer 创建用户解析器,它从 Mongoose 架构生成它们,例如:

用户模型

import mongoose, { Schema } from 'mongoose';
import timestamps from 'mongoose-timestamp';
import bcrypt from 'mongoose-bcrypt';
import { composeWithMongoose } from 'graphql-compose-mongoose';

export const UserSchema = new Schema(
    {
        name: {
            type: String,
            trim: true,
            required: true,
        },
        email: {
            type: String,
            lowercase: true,
            trim: true,
            unique: true,
        },
        phone: {
            type: Number,
            trim: true,
            unique: true,
        },
        password: {
            type: String,
            bcrypt: true,
        },
        type: {
            type: String,
        },
        image: {
            type: String,
            trim: true,
            lowercase: true,
        },
    },
    {
        collection: 'users',
    }
);

UserSchema.plugin(timestamps);
UserSchema.plugin(bcrypt);

UserSchema.index({ createdAt: 1, updatedAt: 1 });

export const User = mongoose.model('User', UserSchema);
export const UserTC = composeWithMongoose(User);

用户架构

import { User, UserTC } from '../models/user';

const UserQuery = {
    userById: UserTC.getResolver('findById'),
    userByIds: UserTC.getResolver('findByIds'),
    userOne: UserTC.getResolver('findOne'),
    userMany: UserTC.getResolver('findMany'),
    userCount: UserTC.getResolver('count'),
    userConnection: UserTC.getResolver('connection'),
    userPagination: UserTC.getResolver('pagination'),
};

const UserMutation = {
    userCreateOne: UserTC.getResolver('createOne'),
    userCreateMany: UserTC.getResolver('createMany'),
    userUpdateById: UserTC.getResolver('updateById'),
    userUpdateOne: UserTC.getResolver('updateOne'),
    userUpdateMany: UserTC.getResolver('updateMany'),
    userRemoveById: UserTC.getResolver('removeById'),
    userRemoveOne: UserTC.getResolver('removeOne'),
    userRemoveMany: UserTC.getResolver('removeMany'),
};

export { UserQuery, UserMutation };

根据graphql-compose-mongoose documentation 和我的理解,我必须使用addResolver() 方法将解析器添加到ObjectTypeComposer (UserTC),例如:

用户架构

import { User, UserTC } from '../models/user';
import { GraphQLUpload } from 'graphql-upload';

UserTC.addResolver({
    name: 'uploadImage',
    type: 'String',
    args: { userId: 'MongoID!', image: 'Upload!' },
    resolve: async ({ source, args, context, info }) => {
        const user = await User.findById({ _id: args.userId }).exec();
        console.log(user);
    }
});

const UserQuery = {
    ...
};

const UserMutation = {
    ...
    uploadImage: UserTC.getResolver('uploadImage'),
};

export { UserQuery, UserMutation };

这一直有效,直到我将 image 参数类型从 String 更改为 Upload。其中,根据Apollo documentation默认开启。

我在控制台中收到此错误:Error: Type with name "Upload" does not exists

但在这种情况下,我不确定如何使用 composeWithMongoose() 添加到我自己的类型定义中。

我很想听听其他方法 - 也许使用完全不同的方法是完全有效的。

编辑 1:回应@Daniel Rearden

我仍然收到Upload 类型不存在:

  throw new Error(`Type with name ${(0, _misc.inspect)(typeName)} does not exists`);

 ^

错误:名称为“上传”的类型不存在

  1. 我已安装:express-graphqlapollo-upload-server
  2. 我将中间件添加到服务器配置中:
import dotenv from 'dotenv';
import express from 'express';
import { ApolloServer } from 'apollo-server-express';
import mongoose from 'mongoose';
import bodyParser from 'body-parser';
import { apolloUploadExpress } from 'apollo-upload-server'; 
import './utils/db';
import schema from './schema';

dotenv.config();

const app = express();

app.use(
    bodyParser.json(),
    apolloUploadExpress()
);

const server = new ApolloServer({
    schema,
    cors: true,
    playground: process.env.NODE_ENV === 'development' ? true : false,
    introspection: true,
    tracing: true,
    path: '/',
});
...
  1. 我在 Schema 索引中提供了以下代码:
import { SchemaComposer } from 'graphql-compose';
import { GraphQLUpload } from 'apollo-upload-server';

import db from '../utils/db'; //eslint-disable-line no-unused-vars

const schemaComposer = new SchemaComposer();

schemaComposer.add(GraphQLUpload);
...

我仍然收到错误消息:Error: Type with name "Upload" does not exists

编辑 2:另外,作为对@Daniel Rearden 的回应

好吧,我刚刚将自定义解析器添加到 UserMutation 架构中并且它起作用了:

const UserMutation = {
    userCreateOne: UserTC.getResolver('createOne'),
    userCreateMany: UserTC.getResolver('createMany'),
    userUpdateById: UserTC.getResolver('updateById'),
    userUpdateOne: UserTC.getResolver('updateOne'),
    userUpdateMany: UserTC.getResolver('updateMany'),
    userRemoveById: UserTC.getResolver('removeById'),
    userRemoveOne: UserTC.getResolver('removeOne'),
    userRemoveMany: UserTC.getResolver('removeMany'),
    uploadImage: {
        type: 'String',
        args: {
            userId: 'String!',
            image: 'Upload'
        },
        resolve: async (_, { userId, image }) => {
            const user = await User.findById({ _id: userId}).exec();
            console.log(user);
        },
    }
};

【问题讨论】:

    标签: node.js express mongoose graphql apollo


    【解决方案1】:

    如文档所述:

    注意:当使用 typeDefs 时,Apollo Server 会将标量 Upload 添加到您的模式中,因此应删除类型定义中任何现有的标量 Upload 声明。如果您使用 makeExecutableSchema 创建架构并使用架构参数将其传递给 ApolloServer 构造函数,请确保包含标量上传。

    如果您没有使用typeDefsresolvers 选项,而是将schema 直接传递给ApolloServer 的构造函数,则必须自己添加标量。 graphql-compose 的文档显示 how to do this 但它应该很简单:

    import { schemaComposer } from 'graphql-compose'
    import { GraphQLUpload } from 'apollo-server'
    
    schemaComposer.add(GraphQLUpload)
    

    【讨论】:

    • 感谢您的回答,我已编辑问题以回复您。
    • 到目前为止我发现的唯一方法是在架构索引文件中的schemaComposer.Mutation.addFields() 中添加自定义解析器。但是我需要访问Ùser 模型。
    猜你喜欢
    • 2021-06-19
    • 2022-10-14
    • 2020-11-19
    • 1970-01-01
    • 2020-04-05
    • 2021-05-16
    • 2020-03-07
    • 1970-01-01
    • 2019-03-05
    相关资源
    最近更新 更多