修改Mongoose查询返回记录数组属性的正确方法是什么?
问题根因
- Mongoose的
find方法默认返回的是Mongoose Document实例,不是普通JS对象,默认不允许直接修改未在schema中定义的属性、或者直接覆盖原有属性值 - 你在
then里使用了forEach,这个方法没有返回值,最终赋值给images的会是undefined,而不是处理后的数组
推荐解决方案
方案1:使用.lean()返回普通JS对象(最常用,性能最优)
如果你的查询是只读场景,不需要后续调用Mongoose文档的实例方法,直接在查询链上加lean(),会直接返回普通JS对象,可随意修改属性:
const images = await tbl .find({ creator_id: req.user._id, }) .select({ creator_id: 0, }) .lean() // 新增这行 .then((images) => { // 遍历修改后返回数组 return images.map(image => { image.file_name = process.env.IMAGE_HOST_URL + image.file_name return image }) })
方案2:使用Document的.set()方法修改属性
如果你需要保留Mongoose文档实例的功能,修改属性时调用内置的set方法即可生效:
const images = await tbl .find({ creator_id: req.user._id, }) .select({ creator_id: 0, }) .then((images) => { images.forEach(image => { // 调用set方法修改属性 image.set('file_name', process.env.IMAGE_HOST_URL + image.file_name) }) return images })
方案3:Schema定义虚拟字段(一劳永逸)
如果所有查询file_name的场景都需要拼接前缀,可以直接在表对应的Schema里定义虚拟属性,不用每次查询手动处理:
// 定义Schema时添加 imageSchema.virtual('file_url').get(function() { return process.env.IMAGE_HOST_URL + this.file_name }) // 配置开启虚拟字段序列化 imageSchema.set('toJSON', { virtuals: true }) imageSchema.set('toObject', { virtuals: true })
后续查询返回的文档会自动携带file_url字段,值为拼接好的完整地址。
内容的提问来源于stack exchange,提问作者Bear Bile Farming is Torture
相关产品推荐
相关产品推荐

