Как сопоставить модели Mongoose с генерируемыми типами GraphQL в NestJS?

Вопрос или проблема

Я использую Typegoose с mongoose-autopopulate и пытаюсь вернуть заполненную модель внутри моего резолвера. Однако я получаю ошибку Ref<SomeReference> не может быть присвоен SomeReference>, отсутствует _id, name....

Кроме как сделать поле ссылки объектом вместо ObjectID, есть ли какие-либо возможные обходные пути для этого? Спасибо.

Куски кода


Модели Mongoose:

@plugin(autopopulate as any)
export class Collection extends TimeStamps {
  @prop()
  public name!: string;

  @prop({ autopopulate: true, ref: () => SomeReference })
  public link?: Ref<SomeReference>;
}
export class SomeReference extends TimeStamps {
  @prop()
  public name!: string;
}

Схема GraphQL (я использую schema-first в NestJS):

type Collection {
    _id: ID!
    name: String!
    link: SomeReference
}

Метод резолвера:

private toPopulatedField(collection: CollectionDocument): Collection {
    return {
      _id: collection._id.toString(),
      name: collection.name,
      // link: {
      //   _id: collection.link._id.toString(),
      //   name: collection.link.name, --> ошибка: имя не существует в ObjectID
      // },
    };
}

Ответ или решение

Чтобы сопоставить пополненные модели Mongoose с созданными типами GraphQL в NestJS, вам необходимо правильно обрабатывать возвращаемые данные и убедиться, что типы ваших полей соответствуют ожидаемым GraphQL типам. Давайте разберёмся с вашей проблемой, основываясь на предоставленных вами кодах.

Проблема

Ошибка, с которой вы столкнулись, связана с тем, что поле link в вашем классе Collection имеет тип Ref<SomeReference>, но GraphQL ожидает, что это будет объект типа SomeReference. При этом, если link не был инициализирован (т.е. равно null или undefined), попытка доступа к collection.link._id и collection.link.name приведет к ошибке, потому что вы пытаетесь получить доступ к свойствам объекта, который не существует.

Решение

  1. Изменение метода сопоставления: Убедитесь, что перед тем, как извлекать свойства link, вы проверяете, что он существует. Если объект ссылки существует, вы можете безопасно получить его свойства.

  2. Корректное определение типов: Убедитесь, что в GraphQL определены все возможные типы, которые вы можете вернуть. В этом случае ваш SomeReference должен корректно определять все поля, которые вы хотите вернуть.

Вот исправленный пример вашего кода:

// Модель Mongoose
@plugin(autopopulate as any)
export class Collection extends TimeStamps {
  @prop()
  public name!: string;

  @prop({ autopopulate: true, ref: () => SomeReference })
  public link?: Ref<SomeReference>;
}

export class SomeReference extends TimeStamps {
  @prop()
  public name!: string;
}

// GraphQL схема (schema-first подход)
type Collection {
    _id: ID!
    name: String!
    link: SomeReference
}

// Модифицированный метод резолвера
private toPopulatedField(collection: CollectionDocument): Collection {
    return {
        _id: collection._id.toString(),
        name: collection.name,
        link: collection.link ? {
            _id: collection.link._id.toString(),
            name: collection.link.name
        } : null, // Проверяем, существует ли ссылка
    };
}

Дополнительные рекомендации

  • Проверка на null и undefined: Всегда полезно проверять, существует ли объект перед доступом к его свойствам, чтобы избежать ошибок выполнения.

  • Убедитесь, что Mongoose правильно находит и заполняет объекты: Если вы используете mongoose-autopopulate, убедитесь, что связи между коллекциями определены корректно, и Mongoose знает, как их заполнять.

  • Логирование: В процессе отладки может быть полезно использовать логирование, чтобы видеть, какие поля возвращаются на каждом уровне.

Заключение

Следуя приведенным выше рекомендациям и упрощая ваш метод маппинга, вы сможете правильно сопоставить свои модели Mongoose с типами GraphQL в NestJS. Это поможет избежать ошибок типизации и обеспечит, чтобы данные возвращались в ожидаемом формате.

Оцените материал
Добавить комментарий

Капча загружается...