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

MongoDB更新用户数据报错求助:多种方法尝试无效

问题描述

更新MongoDB用户数据时触发报错(错误截图如下),尝试过findOneAndUpdate、updateOne等方法均无效。

错误截图

相关代码

mainController

updateUser: async (req, res) => {
    try {
        const updatedUser = await UserSchema.updateOne({ secret: req.params.secret }, { $set: req.body });
        res.status(200).json(updatedUser);
    } catch (error) {
        res.status(400).json({ message: error.message });
    }
},

路由配置

mainRouter.post('/update/:secret', updateUser)

前端React代码

import React, { useState, useEffect } from 'react';
import { Link, useParams, useNavigate } from 'react-router-dom';
import Toolbar from '../components/Toolbar';
import { get, post } from '../helper/helper';

export default function TestPage() {

    const [current, setCurrent] = useState('')
    const [index, setIndex] = useState(0);
    const [allUsers, getAllUsers] = useState([])
    const secret = window.localStorage.getItem('secret')
    const nav = useNavigate()

    useEffect(() => {
        async function currentUser() {
            const resp = get(`user/${secret}`)
            setCurrent(resp)
        }
        currentUser()
    }, [])

    useEffect(() => {
        async function fetchUsers() {
            const resp = await get('api')
            getAllUsers(resp)
        }
        fetchUsers()
    }, [])

    allUsers.filter(user => user.secret !== secret)
    console.log(index)
    const currentUser = allUsers[index];

    async function postLiked() {
        const likedObj = {
            liked: [currentUser]
        }
        const likesObj = {
            likes: [current]
        }
        await post(`update/${current.secret}`, likedObj)
        await post(`update/${currentUser.secret}`, likesObj)
    }

    async function postDislike() {
        const dislikeObj = {
            disliked: [currentUser]
        }
        await post(`update/${current.secret}`, dislikeObj)
    }


    return (
        <div className='home__page'>
            <Toolbar />
            <div className="home__users">
                <div className='single__user'>
                    <img src={currentUser && currentUser.image[0]} alt="" />
                    <h3>{currentUser && `${currentUser.firstName} ${currentUser.lastName}`}</h3>
                    <h4>{currentUser && currentUser.gender}</h4>
                    <button onClick={() => { setIndex(index + 1); postDislike(); nav(`/${currentUser.secret}`) }}>Dislike</button>
                    <button onClick={() => { setIndex(index + 1); postLiked(); nav(`/${currentUser.secret}`) }}>Like</button>
                </div>
            </div>
            <footer className='footer'>
                <p>All rights reserved by Cartoon Match organization. To read more about our policy <Link to='/policy'>click here</Link>. </p>
            </footer>
        </div>
    )
}

helper.js代码

export const get = async (url) => {
    const options = {
        method: 'GET',
        headers: {
            'Content-type': 'application/json',
        },
    };
    const response = await fetch(`http://localhost:4000/${url}`, options);
    if (response.ok) {
        const dataFromGetRequest = await response.json();
        return dataFromGetRequest;
    }
};

export const post = async (body, url) => {
    const options = {
        method: 'POST',
        headers: {
            'Content-type': 'application/json',
        },
        body: JSON.stringify(body),
    };
    const response = await fetch(`http://localhost:4000/${url}`, options);
    if (response.ok) {
        const dataFromPostRequest = await response.json();
        return dataFromPostRequest;
    }
};

export const put = async (body, url) => {
    const options = {
        method: 'PUT',
        headers: {
            'Content-type': 'application/json',
        },
        body: JSON.stringify(body),
    };
    const response = await fetch(`http://localhost:4000/${url}`, options);
    if (response.ok) {
        const dataFromPostRequest = await response.json();
        return dataFromPostRequest;
    }
};
解决方案

排查后发现几个核心问题,逐一修复即可解决更新失败:

1. 修复helper中post/put方法的参数顺序

当前post、put方法定义是(body, url),但前端调用时传的是(url, body),导致后端接收到的req.body是字符串而非更新对象。调整参数顺序并添加错误处理:

export const post = async (url, body) => {
    const options = {
        method: 'POST',
        headers: { 'Content-type': 'application/json' },
        body: JSON.stringify(body),
    };
    const response = await fetch(`http://localhost:4000/${url}`, options);
    if (response.ok) return await response.json();
    throw new Error(`请求失败,状态码:${response.status}`);
};

export const put = async (url, body) => {
    const options = {
        method: 'PUT',
        headers: { 'Content-type': 'application/json' },
        body: JSON.stringify(body),
    };
    const response = await fetch(`http://localhost:4000/${url}`, options);
    if (response.ok) return await response.json();
    throw new Error(`请求失败,状态码:${response.status}`);
};

2. 修复前端get请求未加await的问题

currentUser函数中调用get未加await,导致current存储的是Promise对象,后续current.secret为undefined,后端无法匹配文档:

useEffect(() => {
    async function currentUser() {
        const resp = await get(`user/${secret}`);
        setCurrent(resp);
    }
    currentUser();
}, [secret]);

3. 改用$push/$addToSet更新数组字段

用$set会直接覆盖原有数组,正确做法是用$push添加元素,需要去重则用$addToSet:

updateUser: async (req, res) => {
    try {
        const updateObj = {};
        Object.keys(req.body).forEach(key => {
            if (Array.isArray(req.body[key])) {
                updateObj['$push'] = updateObj['$push'] || {};
                updateObj['$push'][key] = req.body[key][0];
                // 去重替换:updateObj['$addToSet'][key] = req.body[key][0];
            } else {
                updateObj['$set'] = updateObj['$set'] || {};
                updateObj['$set'][key] = req.body[key];
            }
        });

        const updatedUser = await UserSchema.updateOne(
            { secret: req.params.secret },
            updateObj,
            { new: true }
        );
        res.status(200).json(updatedUser);
    } catch (error) {
        res.status(400).json({ message: error.message });
    }
},

4. 遵循RESTful规范改用PUT方法

更新资源建议用PUT而非POST,修改路由并调整前端调用:

// 路由配置
mainRouter.put('/update/:secret', updateUser);

// 前端postLiked/postDislike中替换post为put
await put(`update/${current.secret}`, likedObj);
await put(`update/${currentUser.secret}`, likesObj);
// postDislike同理

5. 修复用户数组过滤逻辑

原过滤代码未保存结果,导致可能匹配到当前用户自己:

const filteredUsers = allUsers.filter(user => user.secret !== secret);
const currentUser = filteredUsers[index];

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 15:10:41