I have a basic Nestjs - Mongoose - Graphql api with I have two schemas defined: User and Event
//USER Schema
@Schema()
export class User extends Document {
@Prop()
username: string;
@Prop({ required: true })
password: string;
@Prop({ required: true, unique: true })
email: string;
@Prop({ required: true, unique: true })
handle: string;
@Prop()
avatar: string;
}
export const UserSchema = SchemaFactory.createForClass(User);
//EVENT schema
@Schema()
export class Event extends Document {
@Prop({
type: MongooseSchema.Types.ObjectId,
ref: User.name,
required: true,
})
creator: GqlUser;
@Length(5, 30)
@Prop({ required: true })
title: string;
@Length(5, 200)
@Prop({ required: true })
description: string;
@Prop()
createdDate: string;
@Prop()
public: boolean;
@Prop()
active: boolean;
}
export const EventSchema = SchemaFactory.createForClass(Event);
In the EventSchema, field creator is typed as MongooseSchema.Types.ObjectId pointing at User
My events.resolvers.ts looks like this:
@Resolver(of => GqlEvent)
export class EventsResolvers {
constructor(private eventsService: EventsService) {}
@Query(returns => [GqlEvent])
async events() {
return this.eventsService.findAll();
}
@Mutation(returns => GqlEvent)
async createEvent(
@Args('createEventInput') createEventInput: CreateEventDto,
) {
return this.eventsService.create(createEventInput);
}
}
event Dtos :
@ObjectType()
export class GqlEvent {
@Field(type => ID)
id: string;
@Field(type => GqlUser)
creator: GqlUser;
@Field()
title: string;
@Field()
description: string;
@Field()
createdDate: string;
@Field()
public: boolean;
@Field()
active: boolean;
}
@InputType()
export class CreateEventDto {
@Field(type => ID)
creator: GqlUser;
@Field()
@Length(5, 30)
title: string;
@Field()
@Length(5, 200)
description: string;
@Field()
@IsBoolean()
public: boolean;
}
With such, Nestjs generates following gql schema (I skip the parts related to user CRUD for clarity) :
# ------------------------------------------------------
# THIS FILE WAS AUTOMATICALLY GENERATED (DO NOT MODIFY)
# ------------------------------------------------------
type GqlUser {
id: ID!
username: String!
handle: String!
avatar: String!
email: String!
}
type GqlEvent {
id: ID!
creator: GqlUser!
title: String!
description: String!
createdDate: String!
public: Boolean!
active: Boolean!
}
type Query {
events: [GqlEvent!]!
}
type Mutation {
createEvent(createEventInput: CreateEventDto!): GqlEvent!
}
input CreateEventDto {
creator: ID!
title: String!
description: String!
public: Boolean!
}
What works : the createEvent mutation correctly inserts a document in database :
{
"_id":{"$oid":"5f27eacb0393199e3bab31f4"},
"creator":{"$oid":"5f272812107ea863e3d0537b"},
"title":"test event",
"description":"a test description",
"public":true,
"active":true,
"createdDate":"Mon Aug 03 2020",
"__v":{"$numberInt":"0"}
}
My problem : I have the following error when I try to request subfields of creator :
Gql query :
query {
events {
id
creator {
id
}
createdDate
public
description
title
active
}
}
Response :
"errors": [
{
"message": "ID cannot represent value: <Buffer 5f 27 28 12 10 7e a8 63 e3 d0 53 7b>",
"locations": [
{
"line": 6,
"column": 7
}
],
"path": [
"createEvent",
"creator",
"id"
],
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"exception": {
"message": "ID cannot represent value: <Buffer 5f 27 28 12 10 7e a8 63 e3 d0 53 7b>",
"stacktrace": [
"GraphQLError: ID cannot represent value: <Buffer 5f 27 28 12 10 7e a8 63 e3 d0 53 7b>",...
As it works fine when I omit creator field, I understand the mongoose MongooseSchema.Types.ObjectId causes problem with gql schema... but I could not find the appropriate way to fix it. Thx in advance for help
It actually had to to with the fact that creator field was not populated.
Changing from
async findAll(): Promise<Event[]> {
return this.eventModel
.find()
.exec();
}
to
async findAll(): Promise<Event[]> {
return this.eventModel
.find()
.populate('creator')
.exec();
}
Fixed my problem. The error message was kind of misleading.
Make sure to populate the field that contains the id you want to display.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With