使用MongoDB聚合框架转换对象并计算字段值差值的实现问题
方案说明
首先需要纠正你预期结果的格式问题:JSON 规范不允许单个对象内存在重复的键,你给出的预期结果里每个对象同时存在两个name和两个data字段,实际无法正常存储和使用,因此下面的方案会将两个配对的原始对象分别存入itemA和itemB字段,避免键冲突。
聚合查询代码
// 你可以直接把这个管道传给mongoose的Model.aggregate()方法使用 const aggregationPipeline = [ // 收集集合内所有文档到同一个数组 { $group: { _id: null, allItems: { $push: "$$ROOT" } } }, // 生成所有两两有序配对,同时计算价格差值 { $project: { pairs: { $reduce: { input: "$allItems", initialValue: [], in: { $concatArrays: [ "$$value", { $map: { input: { // 过滤掉自身和自身配对的情况 $filter: { input: "$allItems", cond: { $ne: ["$$this._id", "$$item._id"] } } }, as: "secondItem", in: { itemA: "$$item", itemB: "$$secondItem", // 差值 = 第一个商品价格 - 第二个商品价格 difference: { $subtract: ["$$item.data.price.last", "$$secondItem.data.price.last"] } } } } ] } } } } }, // 将配对数组拆分为独立文档 { $unwind: "$pairs" }, // 调整输出结构,将配对对象作为根文档返回 { $replaceRoot: { newRoot: "$pairs" } } ];
可选过滤步骤
如果你只需要你示例中列出的4种特定配对,可以在上述管道的最后新增一个$match阶段过滤结果:
{ $match: { $or: [ { "itemA.name": "Helicopter", "itemB.name": "Car" }, { "itemA.name": "Car", "itemB.name": "Truck" }, { "itemA.name": "Truck", "itemB.name": "Helicopter" }, { "itemA.name": "Car", "itemB.name": "Helicopter" } ] } }
内容的提问来源于stack exchange,提问作者Leonid Varygin
相关产品推荐
相关产品推荐

