Mongoose虚拟属性fullName查询未返回问题求助
解决Mongoose虚拟属性fullName在lean查询中不返回的问题
这个问题的核心原因很明确——你用了.lean()方法,它会让Mongoose返回普通JavaScript对象而非Mongoose Document实例,而你定义的fullName虚拟属性是依附于Document实例的,所以普通对象里不会自动带上这个属性。下面给你两种可行的解决方案:
方案一:移除.lean()并配置Schema包含虚拟属性
如果你可以放弃.lean()的性能优势,或者需要利用Mongoose Document的其他特性,这个方案更合适:
首先修改你的Schema定义,添加toJSON和toObject配置,让虚拟属性在转换为普通对象或JSON时被包含:
const chatUserSchema = new mongoose.Schema({ chatBotId: String, firstName: String, lastName: String, contactId: String, type: String, userId: String, BotResponseBlocked: Boolean }, { // 开启虚拟属性在转换时的可见性 toJSON: { virtuals: true }, toObject: { virtuals: true } }); // 保持你的虚拟属性定义不变 chatUserSchema.virtual('fullName').get(function(){ return `${this.firstName} ${this.lastName}`; });
然后修改查询语句,移除.lean(),如果需要得到普通对象,可以用toObject()或toJSON()转换查询结果:
chatUsersModel.find({chatBotId: chatBotId}, {'_id':0,'userId':1, 'firstName':1, 'lastName':1}) .exec((err, result) => { if (err) { // 这里处理错误逻辑 console.error(err); return; } // 将Document实例转换为包含虚拟属性的普通对象 const plainResult = result.map(doc => doc.toObject()); console.log(plainResult); // 此时结果中会包含fullName字段 });
方案二:保留.lean()并通过transform手动添加字段
如果因为性能或其他原因必须使用.lean(),可以利用Mongoose的lean()选项中的transform函数,手动计算并添加fullName字段:
chatUsersModel.find({chatBotId: chatBotId}, {'_id':0,'userId':1, 'firstName':1, 'lastName':1}) .lean({ transform: (doc) => { // 手动拼接fullName doc.fullName = `${doc.firstName} ${doc.lastName}`; // 可选:如果不需要保留firstName和lastName,可以删除它们 // delete doc.firstName; // delete doc.lastName; return doc; } }) .exec((err, result) => { if (err) { console.error(err); return; } console.log(result); // 结果中会包含fullName字段 });
方案选择建议
- 方案一适合需要Mongoose Document实例特性(比如方法、中间件)的场景,代码更符合Mongoose的设计规范。
- 方案二更适合追求查询性能、只需要纯数据对象的场景,避免了Document实例的额外开销。
内容的提问来源于stack exchange,提问作者shamon shamsudeen
相关产品推荐
相关产品推荐

