如何使用Mongoose从Catalog集合关联获取订单商品详情
实现订单与Catalog商品详情的关联查询
先明确集合结构示例
Catalog集合文档
{ "_id": ObjectId("60d21b4667d0d8992e610c85"), "sellerId": "seller_123", "products": [ { "productId": "prod_001", "name": "无线蓝牙耳机", "price": 199, "stock": 50 }, { "productId": "prod_002", "name": "快充充电头", "price": 49, "stock": 200 } ] }
Order集合文档
{ "_id": ObjectId("60d21b8967d0d8992e610c86"), "orderId": "ord_789", "buyerId": "buyer_456", "items": [ { "productId": "prod_001", "quantity": 1 }, { "productId": "prod_002", "quantity": 2 } ], "orderDate": ISODate("2024-05-20T10:30:00Z") }
解决方案:用MongoDB聚合框架关联查询
方法1:先拆分再合并(适合新手理解)
通过$unwind拆分数组,关联后再重新聚合订单结构:
db.orders.aggregate([ // 拆分订单的商品项数组 { $unwind: "$items" }, // 关联Catalog集合,匹配包含当前商品的卖家文档 { $lookup: { from: "catalogs", localField: "items.productId", foreignField: "products.productId", as: "catalogInfo" } }, // 拆分关联得到的Catalog数组 { $unwind: "$catalogInfo" }, // 拆分Catalog中的商品数组 { $unwind: "$catalogInfo.products" }, // 过滤出与订单商品ID匹配的详情 { $match: { $expr: { $eq: ["$items.productId", "$catalogInfo.products.productId"] } } }, // 重组字段结构 { $project: { orderId: 1, buyerId: 1, orderDate: 1, items: { quantity: "$items.quantity", product: "$catalogInfo.products" }, sellerId: "$catalogInfo.sellerId" } }, // 按订单ID重新聚合,恢复商品数组结构 { $group: { _id: "$_id", orderId: { $first: "$orderId" }, buyerId: { $first: "$buyerId" }, orderDate: { $first: "$orderDate" }, sellerId: { $first: "$sellerId" }, items: { $push: "$items" } } } ])
方法2:用子管道关联(更高效)
直接在$lookup的子管道里处理商品匹配,避免多次拆分:
db.orders.aggregate([ { $lookup: { from: "catalogs", let: { orderItems: "$items" }, pipeline: [ // 拆分Catalog的商品数组 { $unwind: "$products" }, // 匹配订单中存在的商品ID { $match: { $expr: { $in: ["$products.productId", { $map: { input: "$$orderItems", as: "item", in: "$$item.productId" } }] } } }, // 只保留需要的字段 { $project: { _id: 0, sellerId: 1, product: "$products" } } ], as: "productDetails" } }, // 将订单商品与对应详情合并 { $addFields: { items: { $map: { input: "$items", as: "item", in: { quantity: "$$item.quantity", product: { $first: { $filter: { input: "$productDetails", cond: { $eq: ["$$this.product.productId", "$$item.productId"] } } } } } } }, // 提取卖家ID(若订单商品来自多卖家,需调整为每个item带对应sellerId) sellerId: { $first: "$productDetails.sellerId" } } }, // 移除临时字段 { $project: { productDetails: 0 } } ])
性能优化建议
为Catalog集合的商品ID字段创建索引,加速关联查询:
db.catalogs.createIndex({"products.productId": 1})
内容的提问来源于stack exchange,提问作者Abdul Azeez TP
相关产品推荐
相关产品推荐

