MongoDB按fighterId分组并转换购物车数据格式的技术需求
MongoDB购物车数据分组与格式转换实现
需求说明
在MongoDB中对用户购物车数据按fighterId进行分组,转换为指定的结构化格式,当用户请求查看购物车时返回该格式的数据。
用户信息模型(User Schema)
const mongoose = require("mongoose"); const Schema = mongoose.Schema; const userSchema = new Schema( { email: { type: String, required: true, unique: true, }, password: { type: String, required: true, }, userName: { type: String, unique: true, }, firstName: { type: String, }, lastName: { type: String, }, currency: { type: String, }, promotionCompany: { type: String, }, displayNameInPublicRankingPage: { type: Boolean, default: false, }, surpriceContribution: { type: Boolean, default: false, }, surpriceContributionAmount: { type: String, }, profileImage: { type: String, }, bannerImage: { type: String, }, setAutoPost: { type: Boolean, default: false, }, agreeTermConditions: { type: Boolean, default: false, }, status: { type: String, default: true, }, role: { type: String, enum: ["fighter", "companion"], default: "fighter", }, followers: [ { type: mongoose.Schema.Types.ObjectId, ref: "User", }, ], cart: [ { shopType: { type: String, enum: ["goal", "surprise"], default: "goal", }, goal: { type: mongoose.Schema.Types.ObjectId, ref: "Goal" }, quantity: Number, goalType: String, amount: String, senderMessage: String, fighterId: String, }, ], socialLinks: [ { platform: { type: String, enum: [ "Facebook", "Twitter", "Instagram", "LinkedIn", "Tiktok", "Other", ], // 根据需要调整 required: true, }, link: { type: String, required: true, }, status: { type: Boolean, default: true, }, }, ], }, { timestamps: true, } ); module.exports = mongoose.model("User", userSchema);
目标信息模型(Goal Schema)
const mongoose = require('mongoose'); const Schema = mongoose.Schema; const goalSchema = new Schema({ goalName: { type: String, required: true, }, goalPrice: { type: Number, required: true, }, goalType: { type: String, enum: ['single', 'subscription', 'crowd'], default: 'single', }, goalPurchaseType: { type: String, enum: ['single', 'multiple'], default: 'multiple', }, goalCategory: { type: String, required: true, }, goalImage: { type: String, required: true, }, status: { type: String, enum: ['active', 'unactive'], default: 'active', }, creator: { type: Schema.Types.ObjectId, ref: 'User', required: true } },{ timestamps: true, }); module.exports = mongoose.model('Goal', goalSchema);
期望输出格式
{ "cart": [ { "wisher": { "wisher_id": "63325fa1743c2a0004f30b29", "name": "Goddess Mariah", "userName": "ineeddmariah", "profileImage": "https://wishtender.s3.amazonaws.com/images/profileImages/6df12e17-793c-4159-9fb3-3fa7af2d712f.png", "Wishercurrency": "USD" }, "cartItem": [ { "id": "cart_id", "goalType": "tip", "quantity": 1, "goalImage": "goal_image", "goalPurchaseType": "single", "goalName": "example_goal_name", "goalPrice": "209" } ] } // 可添加更多分组后的购物车项 ] }
实现方案
使用MongoDB聚合框架结合Mongoose查询,完成分组与格式转换:
Mongoose聚合查询代码
const mongoose = require('mongoose'); const User = require('./models/User'); const Goal = require('./models/Goal'); async function getFormattedCart(userId) { const result = await User.aggregate([ // 匹配当前请求购物车的用户 { $match: { _id: mongoose.Types.ObjectId(userId) } }, // 展开购物车数组,方便逐个处理项 { $unwind: "$cart" }, // 关联Goal集合,获取目标详情 { $lookup: { from: "goals", localField: "cart.goal", foreignField: "_id", as: "cart.goalDetails" } }, // 展开关联后的目标详情数组 { $unwind: "$cart.goalDetails" }, // 按fighterId分组,聚合愿望者信息和对应购物车项 { $group: { _id: "$cart.fighterId", wisher: { $first: { wisher_id: "$cart.fighterId", name: { $concat: ["$firstName", " ", "$lastName"] }, userName: "$userName", profileImage: "$profileImage", Wishercurrency: "$currency" } }, cartItem: { $push: { id: "$cart._id", goalType: "$cart.goalType", quantity: "$cart.quantity", goalImage: "$cart.goalDetails.goalImage", goalPurchaseType: "$cart.goalDetails.goalPurchaseType", goalName: "$cart.goalDetails.goalName", goalPrice: { $toString: "$cart.goalDetails.goalPrice" } } } } }, // 移除不需要的_id字段 { $project: { _id: 0, wisher: 1, cartItem: 1 } }, // 将分组结果包裹到cart数组中 { $group: { _id: null, cart: { $push: "$$ROOT" } } }, { $project: { _id: 0, cart: 1 } } ]); return result.length > 0 ? result[0] : { cart: [] }; }
代码说明
- $match:筛选出当前请求购物车的用户。
- $unwind:将用户购物车数组拆分为单个文档,便于后续关联和分组操作。
- $lookup:关联
goals集合,拉取购物车项对应的目标详细信息。 - $unwind:展开关联后的目标详情数组,确保每个购物车项对应一条完整的目标数据。
- $group:按
fighterId分组,聚合生成愿望者信息和该分组下的所有购物车项。 - $project:调整字段结构,移除冗余的
_id。 - 最后两次聚合:将分组后的结果整理成期望的
cart数组格式。
内容的提问来源于stack exchange,提问作者Rahul Kumar
相关产品推荐
相关产品推荐

