我目前正在实现一个演示应用程序,以了解MongoDB的NestJS框架。
我目前面临以下错误消息,我无法修复:
对于模型“Player”的路径“_id”处的值“1”失败+ 40997ms CastError:对于模型“Player”的路径“_id”处的值“1”,转换为ObjectId失败
我的控制器看起来像这样:
@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;
}
我的mongoose schema看起来像这样:
export const PlayerSchema = new mongoose.Schema({
id: Number,
name: String,
score: Number,
createdAt: { type: Date, default: Date.now },
isDeleted: Boolean
});
输入db.players.find()后的mongoDB条目示例
{ "_id" : ObjectId("5e5fccac9d16bf2d325cd57a"), "id" : 1, "name" : "Player One", "score" : 0, "createdAt" : "2020-04-03", "isDeleted" : false }
我在这里做错了什么,或者我如何修复这个错误?
2条答案
按热度按时间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应该是这样的:
如果没有硬性要求将_id字段设置为数字,则可以使用ObjectId值而不是Number,这将为您保存确保_id字段唯一性的压力。为此,请在模式中将_id属性设置为
_id: mongoose.ObjectId
。你还需要更新dto,model和其他你输入播放器对象的地方,以反映模式更新,即添加不同类型的“_id”属性,* 也许 * 删除以前的“id”属性。
如果你想知道_id字段是如何到达那里的;它是每个MongoDB文档的属性,它作为主键。即使您没有将其添加到模式中,MongoDB驱动程序(本例中为mongoose)或mongod服务器也会为您添加它。更多详情
eivgtgni2#
如果你不想修改mongo的默认
_id
,可以使用mongoose的Types.ObjectId.isValid函数检查播放器是否存在。这个示例代码有明显的改进空间,但显示了对这个想法的把握: