Mongoose populate后调用map()出现undefined错误,无法读取email属性的原因排查
回答
嘿,我来帮你梳理下这个问题的解决办法和可以优化的点:
1. 先去掉冗余的await
首先你这段代码里有个小问题:const a = await form.activity.map((a) => a.viewedBy);——map是同步的数组方法,根本不需要加await,这属于多余的写法,直接删掉await就好。
2. 过滤数组里的无效值
既然已经发现数组里有undefined,那最直接的解决方式就是在访问email前先把这些无效元素过滤掉:
const a = form.activity.map(item => item.viewedBy); // 过滤掉undefined后再映射email const emails = a.filter(item => item !== undefined).map(e => e.email); console.log(emails);
或者用更简洁的链式写法,利用Boolean自动过滤假值(包括undefined、null、0等):
const emails = form.activity .map(item => item.viewedBy) .filter(Boolean) .map(e => e.email); console.log(emails);
3. 找到undefined产生的根源
为什么会出现undefined呢?大概率是form.activity里有部分viewedBy引用的User文档不存在(比如被删除了),或者这个字段本身就没设置值。
你可以在populate的时候加个match条件,只拉取有效的User文档:
const form = await Form.findOne({ _id: res._id }).populate({ path: "activity.viewedBy", model: User, match: { _id: { $exists: true } } // 只匹配存在的User记录 });
另外,也可以在Schema层面给activity.viewedBy设置必填约束或者默认值,从源头避免无效引用的出现。
4. 额外的代码优化建议
- 注意你在函数里用的是
res._id和res.user,一般在Express这类框架里,请求相关的数据是存在req对象里的,比如req.params.id或者req.user,这里会不会是笔误?建议检查一下。 - 可以把查询和更新合并成一个操作,用
findByIdAndUpdate减少数据库请求次数:
const updatedForm = await Form.findByIdAndUpdate( res._id, // 这里建议确认是否应该是req._id { $push: { activity: { viewedBy: res.user, date: new Date(), }, }, }, { new: true } // 返回更新后的文档 ).populate({ path: "activity.viewedBy", model: User });
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

