Гнездо JS & MongoDB | CastError: сбой приведения к ObjectId для значения «1» по пути «_id» для модели «Player» - PullRequest
1 голос
/ 17 марта 2020

В настоящее время я внедряю демонстрационное приложение, чтобы познакомиться с инфраструктурой Nest JS с помощью mongoDB.

В настоящее время я сталкиваюсь со следующим сообщением об ошибке, которое не могу исправить:

не удалось для значения «1» в пути «_id» для модели «Player» + 40997ms CastError: Ошибка приведения к ObjectId для значения «1» в пути «_id» для модели «Player»

Мой контроллер выглядит так:

@Controller('/players')
export class PlayersController {
    constructor(private playersService: PlayersService) { }

    @Get('/:id')
    async getPlayer(@Res() res, @Param('id') id: number) {
        const player = await this.playersService.getPlayer(id);
        if (!player) throw new NotFoundException('Player does not exist!');
        return res.status(HttpStatus.OK).json(player);
    }
}

Мой сервис выглядит так:

@Injectable()
export class PlayersService {
    constructor(@InjectModel('Player') private readonly playerModel: Model<Player>) { }

    async getPlayer(playerId: number): Promise<Player | undefined> {
        const player = await this.playerModel.findById(playerId);
        return player;
    }
}

Мой DTO выглядит так:

export class CreatePlayerDto {
    readonly id: number;
    readonly name: string;
    readonly score: number;
    readonly created_at: Date;
    readonly is_deleted: boolean;
}

Моя модель выглядит так :

export class Player extends Document {
    readonly id: number;
    readonly name: string;
    readonly score: number;
    @Exclude() readonly createdAt: Date;
    @Exclude() readonly isDeleted: boolean;
}

Моя схема mon goose выглядит следующим образом:

export const PlayerSchema = new mongoose.Schema({
    id: Number,
    name: String,
    score: Number,
    createdAt: { type: Date, default: Date.now },
    isDeleted: Boolean
});

Пример записи mongoDB после ввода db.players.find ()

{ "_id" : ObjectId("5e5fccac9d16bf2d325cd57a"), "id" : 1, "name" : "Player One", "score" : 0, "createdAt" : "2020-04-03", "isDeleted" : false }

Что я здесь не так делаю или как я могу исправить эту ошибку?

1 Ответ

2 голосов
/ 17 марта 2020

Почему у вас ошибка:
В службе у вас есть этот фрагмент кода, который пытается найти документ игрока из БД: this.playerModel.findById(playerId);

Значение playerId в этом запросе является строкой (или числом после приведения), однако метод mon goose model.findById внутренне делает что-то вроде этого: this.playerModel.find({ _id: playerId }); и из примера вывода БД, который вы добавили в вопрос, вы можете видеть, что _id является ObjectId не строка или число, следовательно, вы получаете ошибку CastError: Cast to ObjectId failed for value “1” at path “_id” for model “Player”

Исправление:
Есть две вещи, которые вы можете сделать :
1. Обновите запрос, чтобы использовать идентификатор вместо _id. Тогда ваш запрос будет выглядеть примерно так: this.playerModel.find({ id: playerId });
2. Обновите вашу схему так, чтобы свойство _id было числом, а не ObjectID (по умолчанию). Если вы сделаете это, вы должны будете убедиться в уникальности значения _id. Ваш запрос не нужно будет менять, если вы это сделаете. Тогда ваша схема будет выглядеть примерно так:

export const PlayerSchema = new mongoose.Schema({
    _id: Number,
    name: String,
    score: Number,
    createdAt: { type: Date, default: Date.now },
    isDeleted: Boolean
});

Если для поля _id нет строгого требования, вы можете использовать значения ObjectId вместо Number, это избавит вас от необходимости обеспечения уникальность поля _id. Для этого установите свойство _id в схеме _id: mongoose.ObjectId.

Вам также необходимо обновить dto, модель и все остальные места, в которых вы напечатали объект player, чтобы отразить обновление схемы, т.е. добавление " _id "свойство с другим типом и возможно удаление прежнего свойства" id ".

Если вам интересно, как попало туда поле _id ; это свойство каждого документа MongoDB, оно служит первичным ключом. Даже если вы не добавите его в свою схему, драйвер MongoDB (в данном случае mon goose) или сервер mongod добавят его за вас. Подробнее здесь

...