You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在JavaScript中一键将多组数组数据保存至MongoDB数据库

问题:MoneyIn交易流程仅保存最后一条商品数据
  • 场景:用户在MoneyIn交易流程中输入多组商品名称、数量、价格等信息,点击蓝色保存按钮时,仅最后一条商品数据存入MongoDB
  • 红色按钮功能:仅隐藏输入区域展示商品列表,不执行保存操作
  • 需求:点击蓝色保存按钮时,同时保存所有商品数据与MoneyIn交易数据,控制台输出所有商品的数组格式

界面截图说明

  1. 商品输入表单:包含商品名称、数量、价格等输入字段,以及添加商品的操作按钮
  2. 商品详情添加后界面:展示已添加的商品列表,隐藏输入区域
  3. 保存按钮高亮界面:突出显示用于保存交易与商品数据的蓝色按钮

代码片段

前端React组件代码

const MoneyIn = () => { 

    const [totalAmountIn, setTotalAmountIn] = useState(0);
    const [amountRecieved, setAmountRecieved] = useState(0);
    const [visible, setVisible] = useState(false);
    const [visible2, setVisible2] = useState(false);
    const [clicked, setClicked] = useState(false);
    const [productName, setProductName] = useState("");
    const [sellingPrice, setSellingPrice] = useState(0);
    const [sellingPriceOfTotal, setSellingPriceOfTotal] = useState(0);
    const [balanceDue, setBalanceDue] = useState(0);
    const [itemDescription, setItemDescription] = useState("");
    const [unitOfQuantity, setUnitOfQuantity] = useState("");
    const [quantityCount, setQuantityCount] = useState(1);
    const [newItems, setNewItems] = useState([]);
    const [moneyInData, setMoneyInData] = useState([]);
    const [modeOfPayment, setModeOfPayment] = useState("");

    let handleSaveItem = () => {
        const newItemData = { productName, sellingPriceOfTotal, quantityCount, unitOfQuantity, sellingPrice };
        setNewItems([...newItems, newItemData]); 
    }

    let handleSaveMonyIn = (event) => {
        event.preventDefault();
        if (totalAmountIn === 0 || itemDescription === "") {
            setSeverity("error")
            setMessage("Enter Amount and Item Description");
            setOpen(true)
        } else if (totalSellingPrice > totalAmountIn) {
            setSeverity("error")
            setMessage("Total Selling Prices cannot be bigger than Total amount");
            setOpen(true)
        }

        else {
            const newMoneyInData = { totalAmountIn, amountRecieved, balanceDue, itemDescription, modeOfPayment };
            setMoneyInData([...moneyInData, newMoneyInData]);
            
            // 保存到数据库
            Axios.post('http://localhost:3500/moneyIn',{
                totalAmountIn, amountRecieved, balanceDue, newItems, itemDescription, modeOfPayment
            }).then((response) => {alert('TRANSACTION CREATED')}).catch(function (error) {
                console.log(error);
              });
            Axios.post('http://localhost:3500/newItems', {productName, sellingPriceOfTotal, quantityCount, unitOfQuantity, 
            sellingPrice,totalSellingPrice}).then((response) => console.log(response)).catch((err)=> console.log(err));
            console.log(newMoneyInData);
            document.getElementById("totalAndRecievedAmt").reset();
            document.getElementById("itemDescriptionFrm").reset();
            setSeverity("success");
            setMessage("Saved Successfully !!!");
            setOpen(true);
             setTotalAmountIn(0);
             setAmountRecieved(0);
             setBalanceDue(0);
             setItemDescription('');
             setNewItems([]);
        }
    }
}

MongoDB Schema代码

MoneyIn交易数据Schema

const mongoose = require ('mongoose')
const moneyInDataSchema = new mongoose.Schema({
    totalAmountIn:{
        type: String,
        required: true
    },
    amountRecieved:{
      type: String,
      required: true
    },
    balanceDue: {
        type: Number
    },
    itemDescription:{
        type: String
    },
    modeOfPayment:{
        type: String,
        required:true
    }
})
module.exports = mongoose.model('MoneyInData', moneyInDataSchema)

商品数据Schema

const mongoose = require('mongoose');
const MoneyInData = require('./MoneyInData');
const newItemsSchema = new mongoose.Schema({
    productName:{
        type: String,
        required: true
    },
    sellingPriceOfTotal:{
      type: String,
      required: true
    },
    quantityCount: {
        type: Number
    },
    unitOfQuantity:{
        type: String
    },
    sellingPrice:{
        type: Number,
        required:true
    },
    sales:{
        type: mongoose.Schema.Types.ObjectId,
        ref: 'MoneyInData'
    }
})
module.exports = mongoose.model('NewItemsData', newItemsSchema);

控制器代码(商品数据增查)

const getAllNewItems = asyncHandler(async (req, res) => {
    const newItemsData = await NewItemsData.find().populate('sales').select().lean()

    if (!newItemsData?.length) {
        return res.status(400).json({ message: 'No rescent transaction' })
    }
    res.json(newItemsData)
})

const createNewItems = asyncHandler(async (req, res) => {
    const { productName, sellingPriceOfTotal, quantityCount, unitOfQuantity, sellingPrice}= req.body

    // 验证数据
    if (!productName || !sellingPriceOfTotal || !quantityCount
        || !unitOfQuantity || !sellingPrice ) {
        return res.status(400).json({ message: 'All fields are required' })
    }

    const newItemsObj = { productName, sellingPriceOfTotal, quantityCount, unitOfQuantity, sellingPrice }
    const addNewItems = await NewItemsData.create(newItemsObj)

    if (addNewItems) {// 创建成功
        res.status(201).json({ message: 'New Item Recorded' })
        console.log(addNewItems)
    } else {
        res.status(400).json({ message: 'Invalid Item' })
    }
})

问题原因与解决方案

核心问题

  1. 前端请求逻辑错误:点击保存交易时,仅发送了当前表单的单个商品字段,而非newItems数组,导致后端只收到最后一条商品数据
  2. 交易与商品关联缺失:未将MoneyIn交易ID绑定到商品的sales字段,无法建立数据关联

修复步骤

1. 前端修改:批量发送商品数组

替换handleSaveMonyIn中的请求逻辑,移除单个商品的POST请求,直接将newItems数组随交易数据一起发送:

// 保留交易请求,移除单独的商品请求
Axios.post('http://localhost:3500/moneyIn',{
    totalAmountIn, amountRecieved, balanceDue, newItems, itemDescription, modeOfPayment
}).then((response) => {
    alert('TRANSACTION CREATED');
    console.log("所有商品数据:", newItems); // 控制台输出商品数组
}).catch(function (error) {
    console.log(error);
});

2. 后端新增MoneyIn控制器:关联交易与商品

先创建交易记录,再批量创建关联商品(绑定交易ID到sales字段):

const createMoneyIn = asyncHandler(async (req, res) => {
    const { totalAmountIn, amountRecieved, balanceDue, newItems, itemDescription, modeOfPayment } = req.body;

    // 验证必填字段
    if (!totalAmountIn || !amountRecieved || !modeOfPayment || !newItems?.length) {
        return res.status(400).json({ message: '交易核心字段和商品数据不能为空' });
    }

    // 1. 创建交易记录
    const moneyIn = await MoneyInData.create({
        totalAmountIn,
        amountRecieved,
        balanceDue,
        itemDescription,
        modeOfPayment
    });

    if (!moneyIn) {
        return res.status(400).json({ message: '创建交易失败' });
    }

    // 2. 批量创建关联商品
    const itemsWithSaleId = newItems.map(item => ({
        ...item,
        sales: moneyIn._id
    }));
    const createdItems = await NewItemsData.insertMany(itemsWithSaleId);

    if (!createdItems?.length) {
        // 商品创建失败时回滚交易
        await MoneyInData.findByIdAndDelete(moneyIn._id);
        return res.status(400).json({ message: '交易创建成功,但商品保存失败' });
    }

    res.status(201).json({ 
        message: '交易和商品数据保存成功',
        transaction: moneyIn,
        items: createdItems
    });
});

3. 前端优化:添加商品后清空输入

在handleSaveItem中添加清空逻辑,避免重复提交同一商品:

let handleSaveItem = () => {
    const newItemData = { productName, sellingPriceOfTotal, quantityCount, unitOfQuantity, sellingPrice };
    setNewItems([...newItems, newItemData]); 
    // 清空当前输入字段
    setProductName("");
    setSellingPrice(0);
    setSellingPriceOfTotal(0);
    setQuantityCount(1);
    setUnitOfQuantity("");
}

内容的提问来源于stack exchange,提问作者Aham_Uzoma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 00:44:58