NodeJS中无法为MongoDB返回对象添加属性值,求解决方案
问题:MongoDB查询返回对象无法添加count、filter属性
我有个NodeJS项目,MongoDB的cart表存了商品项,业务逻辑是先从cart表取商品项,再用itemId去item表拿完整商品信息并验证是否存在。现在想把cart项里的count、filter这些额外属性加到item表返回的对象里,用了下面的代码但没达到预期效果,求帮忙。
代码如下:
router.get("/", userAuth, async (req, res, next) => { try { console.log("running"); const { _id } = req.userInfo; const cartItems = await getAllCartItems(_id); const carts = []; for (const item of cartItems) { const cartItem = await getItemById(item.itemId); if (cartItem?._id) { cartItem.count = item.count; cartItem.filter = item.filter; carts.push(cartItem); } // console.log(cartItem); } carts.length >= 0 && res.json({ status: "success", message: "cart items are returned", carts, }); } catch (error) { next(error); } });
解决方案
1. 转成普通JS对象再添加属性
MongoDB驱动(比如Mongoose)返回的是Document实例,不是普通JS对象,这类对象有结构限制,直接加属性可能不会被序列化到JSON里。解决办法有两种:
- 用
.toObject()转换:
const cartItem = await getItemById(item.itemId); if (cartItem?._id) { const plainItem = cartItem.toObject(); // 转成普通对象 plainItem.count = item.count; plainItem.filter = item.filter; carts.push(plainItem); }
- 查询时直接返回普通对象(Mongoose用
.lean()):
修改getItemById的实现,在查询语句后加.lean():
async function getItemById(itemId) { return await ItemModel.findById(itemId).lean(); // 返回普通JS对象 }
2. 检查属性是否被Schema过滤
如果item表的Mongoose Schema里没定义count、filter字段,默认会过滤掉这些额外属性。转成普通对象后添加就能避开这个问题;如果需要持久化这两个字段,就得在Schema里手动添加。
3. 优化批量查询性能(额外建议)
当前循环挨个查item的方式性能很差,数据量大时会有明显延迟,建议用$in批量查询再匹配属性:
router.get("/", userAuth, async (req, res, next) => { try { console.log("running"); const { _id } = req.userInfo; const cartItems = await getAllCartItems(_id); // 提取所有需要查询的itemId const itemIds = cartItems.map(item => item.itemId); // 批量查询所有商品 const items = await ItemModel.find({ _id: { $in: itemIds } }).lean(); // 匹配cart中的count和filter属性 const carts = items.map(item => { const matchedCart = cartItems.find(cart => cart.itemId.toString() === item._id.toString()); return { ...item, count: matchedCart?.count, filter: matchedCart?.filter }; }); res.json({ status: "success", message: "cart items are returned", carts, }); } catch (error) { next(error); } });
内容的提问来源于stack exchange,提问作者P K Dhee Taal
相关产品推荐
相关产品推荐

