实现思路
- 开启事务:确保更新库存和统计总价操作在同一个事务内,保证数据一致性。
- 更新商品库存:遍历订单中的商品ID列表,找到对应的商品并减少其库存数量。
- 统计订单商品总价:使用聚合管道,通过
$lookup
操作符将订单中的商品ID与products
集合关联,然后使用$sum
操作符计算总价。
- 提交或回滚事务:如果更新库存和统计总价都成功,提交事务;否则,回滚事务。
代码示例(以MongoDB和Node.js为例)
const { MongoClient } = require('mongodb');
// 连接MongoDB
const uri = "mongodb://localhost:27017";
const client = new MongoClient(uri);
async function updateStockAndCalculateTotal(order) {
try {
await client.connect();
const session = client.startSession();
session.startTransaction();
const productsCollection = client.db('ecommerce').collection('products');
const ordersCollection = client.db('ecommerce').collection('orders');
// 更新商品库存
for (const productId of order.productIds) {
await productsCollection.updateOne(
{ _id: productId },
{ $inc: { stock: -1 } },
{ session }
);
}
// 统计订单商品总价
const pipeline = [
{
$match: { _id: order._id }
},
{
$lookup: {
from: 'products',
localField: 'productIds',
foreignField: '_id',
as: 'products'
}
},
{
$unwind: '$products'
},
{
$group: {
_id: null,
totalPrice: { $sum: '$products.price' }
}
}
];
const result = await ordersCollection.aggregate(pipeline).session(session).toArray();
const totalPrice = result[0].totalPrice;
await session.commitTransaction();
return totalPrice;
} catch (error) {
console.error('Transaction failed:', error);
throw error;
} finally {
await client.close();
}
}
// 使用示例
const order = {
_id: '123',
productIds: ['product1Id', 'product2Id']
};
updateStockAndCalculateTotal(order).then(totalPrice => {
console.log('Total Price:', totalPrice);
}).catch(error => {
console.error('Error:', error);
});