如何实现MongoDB跨bookings、invoices多集合的聚合过滤查询
MongoDB聚合查询正确实现方案
原查询存在的问题
$lookup返回的invoiceInfo是数组类型,原查询直接对invoiceInfo.InvoiceData做过滤操作逻辑错误,需要先遍历数组内每个发票文档单独处理- 缺失对
BookingData.products非空非null的前置校验,边界场景会出现异常结果 - 字段存在性校验使用
$ne: [xxx, undefined]兼容性差,改用MongoDB原生$exists操作符更可靠
正确聚合查询代码
db.bookings.aggregate([ // 第一步:过滤bookings基础条件:状态不等于delivered,products字段有效 { $match: { Status: { $ne: "Delivered" }, "BookingData.products": { $exists: true, $ne: null, $not: { $size: 0 } } } }, // 关联invoices集合 { $lookup: { from: "invoices", localField: "Invoices", foreignField: "_id", as: "invoiceInfo" } }, // 过滤符合要求的产品:ProductID存在非空、配送未失败 { $set: { "BookingData.products": { $filter: { input: "$BookingData.products", cond: { $and: [ { $ne: ["$$this.ProductID", null] }, { $exists: "$$this.ProductID" }, { $ne: ["$$this.IsDeliveryFailed", "Yes"] } ] } } } } }, // 遍历每个关联到的发票,过滤符合要求的发票项:InvoiceID存在非空、支付未失败 { $set: { invoiceInfo: { $map: { input: "$invoiceInfo", as: "invoice", in: { $mergeObjects: [ "$$invoice", { InvoiceData: { $filter: { input: { $ifNull: ["$$invoice.InvoiceData", []] }, cond: { $and: [ { $ne: ["$$this.InvoiceID", null] }, { $exists: "$$this.InvoiceID" }, { $ne: ["$$this.IsPaymentFailed", "Yes"] } ] } } } } ] } } } } }, // 最终过滤:只要有效产品/有效发票项任意一项非空就返回,完全匹配预期规则 { $match: { $expr: { $or: [ { $gt: [{ $size: "$BookingData.products" }, 0] }, { $gt: [ { $sum: { $map: { input: "$invoiceInfo", in: { $size: "$$this.InvoiceData" } } } }, 0 ] } ] } } } ])
内容的提问来源于stack exchange,提问作者its me
相关产品推荐
相关产品推荐

