NestJS和MongoDB| CastError:对于模型“Player”的路径“_id”处的值“1”,转换为ObjectId失败

0kjbasz6  于 2023-10-16  发布在  Go
关注(0)|答案(2)|浏览(207)

我目前正在实现一个演示应用程序,以了解MongoDB的NestJS框架。
我目前面临以下错误消息,我无法修复:
对于模型“Player”的路径“_id”处的值“1”失败+ 40997ms CastError:对于模型“Player”的路径“_id”处的值“1”,转换为ObjectId失败
我的控制器看起来像这样:

  1. @Controller('/players')
  2. export class PlayersController {
  3. constructor(private playersService: PlayersService) { }
  4. @Get('/:id')
  5. async getPlayer(@Res() res, @Param('id') id: number) {
  6. const player = await this.playersService.getPlayer(id);
  7. if (!player) throw new NotFoundException('Player does not exist!');
  8. return res.status(HttpStatus.OK).json(player);
  9. }
  10. }

我的服务看起来像这样:

  1. @Injectable()
  2. export class PlayersService {
  3. constructor(@InjectModel('Player') private readonly playerModel: Model<Player>) { }
  4. async getPlayer(playerId: number): Promise<Player | undefined> {
  5. const player = await this.playerModel.findById(playerId);
  6. return player;
  7. }
  8. }

我的DTO看起来像这样:

  1. export class CreatePlayerDto {
  2. readonly id: number;
  3. readonly name: string;
  4. readonly score: number;
  5. readonly created_at: Date;
  6. readonly is_deleted: boolean;
  7. }

我的模型看起来像这样:

  1. export class Player extends Document {
  2. readonly id: number;
  3. readonly name: string;
  4. readonly score: number;
  5. @Exclude() readonly createdAt: Date;
  6. @Exclude() readonly isDeleted: boolean;
  7. }

我的mongoose schema看起来像这样:

  1. export const PlayerSchema = new mongoose.Schema({
  2. id: Number,
  3. name: String,
  4. score: Number,
  5. createdAt: { type: Date, default: Date.now },
  6. isDeleted: Boolean
  7. });

输入db.players.find()后的mongoDB条目示例

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

我在这里做错了什么,或者我如何修复这个错误?

1sbrub3j

1sbrub3j1#

为什么会出现错误:

在这个服务中,你有这样一段代码,它试图从DB中找到一个播放器文档:this.playerModel.findById(playerId);
在该查询中,playerId的值是一个字符串(或转换后的数字),然而,mongoose方法model.findById在内部执行如下操作:this.playerModel.find({ _id: playerId });,从您添加到问题的示例DB输出中,可以看到_id是ObjectId,而不是字符串或数字,因此您会得到错误CastError: Cast to ObjectId failed for value “1” at path “_id” for model “Player”

修复:

你可以做两件事:
1.更新查询以使用id而不是_id。您的查询将是这样的:this.playerModel.find({ id: playerId });
2.更新您的架构,使_id属性为数字而不是ObjectID(默认值)。如果这样做,则必须确保_id值的唯一性。如果您这样做,您的查询将不需要更改。你的schema应该是这样的:

  1. export const PlayerSchema = new mongoose.Schema({
  2. _id: Number,
  3. name: String,
  4. score: Number,
  5. createdAt: { type: Date, default: Date.now },
  6. isDeleted: Boolean
  7. });

如果没有硬性要求将_id字段设置为数字,则可以使用ObjectId值而不是Number,这将为您保存确保_id字段唯一性的压力。为此,请在模式中将_id属性设置为_id: mongoose.ObjectId
你还需要更新dto,model和其他你输入播放器对象的地方,以反映模式更新,即添加不同类型的“_id”属性,* 也许 * 删除以前的“id”属性。

如果你想知道_id字段是如何到达那里的;它是每个MongoDB文档的属性,它作为主键。即使您没有将其添加到模式中,MongoDB驱动程序(本例中为mongoose)或mongod服务器也会为您添加它。更多详情

展开查看全部
eivgtgni

eivgtgni2#

如果你不想修改mongo的默认_id,可以使用mongoose的Types.ObjectId.isValid函数检查播放器是否存在。这个示例代码有明显的改进空间,但显示了对这个想法的把握:

  1. import { Model, Types } from 'mongoose';
  2. ...
  3. async getPlayer(playerId: number) {
  4. try {
  5. const objectId = Types.ObjectId.isValid(playerId) ? new Types.ObjectId(playerId) : null;
  6. if (objectId) {
  7. const player = await this.playerModel.findById(objectId).exec();
  8. if (player) {
  9. return player;
  10. } else {
  11. throw new NotFoundException(`Player with id ${id} not found`);
  12. }
  13. } else {
  14. throw new BadRequestException(`Invalid player ID: ${id}`);
  15. }
  16. } catch (error) {
  17. throw new NotFoundException(`Failed to find player by id ${id}.`);
  18. }
  19. ...
展开查看全部

相关问题