MongoDB聚合查询:筛选跨购物车同时购买P1和P2的客户
正确MongoDB聚合查询实现
你的原查询存在几个核心问题:
- 集合名错误,测试数据写入的是
customer集合,不是shoppingCart - 字段路径错误,测试数据中
SHOPPINGCART直接挂载在CUSTOMER字段下,不存在中间的creates字段 - 匹配逻辑错误:对展开后的单条购物车数据做
$and匹配,要求同一条购物车同时包含两个商品,自然无法匹配跨购物车的场景 - 字段判断错误:测试数据用
purchased: "yes"标识已购买,不存在dateClosed字段,查询的商品ID也和需求不符
正确聚合语句如下:
db.customer.aggregate([ // 第一步:先粗筛,仅保留存在已购购物车包含P1或P2的客户,减少后续运算量 { $match: { $or: [ { "CUSTOMER.SHOPPINGCART": { $elemMatch: { purchased: "yes", "containsProdList.productId": "P1" } } }, { "CUSTOMER.SHOPPINGCART": { $elemMatch: { purchased: "yes", "containsProdList.productId": "P2" } } } ] } }, // 第二步:展开购物车数组 { $unwind: "$CUSTOMER.SHOPPINGCART" }, // 第三步:仅保留已购买的购物车 { $match: { "CUSTOMER.SHOPPINGCART.purchased": "yes" } }, // 第四步:展开购物车中的商品列表 { $unwind: "$CUSTOMER.SHOPPINGCART.containsProdList" }, // 第五步:仅保留我们需要的P1、P2商品记录 { $match: { "CUSTOMER.SHOPPINGCART.containsProdList.productId": { $in: ["P1", "P2"] } } }, // 第六步:按客户ID分组,去重收集该客户所有已购买的目标商品ID { $group: { _id: "$_id", customerId: { $first: "$CUSTOMER.customerId" }, customerName: { $first: "$CUSTOMER.customerName" }, purchasedTargetProds: { $addToSet: "$CUSTOMER.SHOPPINGCART.containsProdList.productId" } } }, // 第七步:仅保留同时购买了P1和P2的客户 { $match: { purchasedTargetProds: { $all: ["P1", "P2"] } } }, // 可选:移除不需要的中间字段 { $project: { purchasedTargetProds: 0 } } ])
查询逻辑说明
- 先通过粗筛过滤完全不符合条件的客户,提升查询效率
- 两次展开分别处理购物车数组、购物车内的商品数组,拿到所有已购的单个商品记录
- 按客户分组后用
$addToSet去重收集所有已购的目标商品,再判断是否同时包含两个商品,自然支持跨购物车的场景
内容的提问来源于stack exchange,提问作者Jaewon Choi
相关产品推荐
相关产品推荐

