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

Mongoose嵌套Schema请求数据未存入数据库问题排查

问题:嵌套数组无法通过PATCH请求更新

我无法理解为何请求数据未存入数据库。我使用Mongoose定义了含嵌套对象的Schema,尝试发送请求更新嵌套对象内的特定数组,请求返回成功但数据未添加。以下是相关代码:

Schema

const personSchema = new mongoose.Schema({
    connections: {
        parents: {type : Array},
        children: {type : Array}
    }
})

路由

router.patch('/v2/:id', getPerson, async (req, res) => {
    if (req.body.connections != null) {
        if (req.body.connections.parents != null) { res.person.connections.parents.push(req.body.connections.parents); }
        if (req.body.connections.children != null) { res.person.connections.children.push(req.body.connections.children); }
    }
    try {
        const updatePerson = await res.person.save();
        res.status(200).json({ message: 'Success' })
    } catch (error) {
        res.status(400).json({ message: error.message })
    }
})

中间件

async function getPerson(req, res, next) {
    let person;
    try {
        person = await Person.findById(req.params.id);
        if (person === null) {
            return res.status(404).json({ message: 'Cannot find the person' });
        }
    } catch (error) {
        return res.status(500).json({ message: error.message });
    }
    res.person = person;
    next();
}

请求

PATCH http://localhost:3100/api-db/v2/62e28682cecc9120c7af9de5
Content-Type: application/json

{
    "connections.parents" : "test"
}

数据库连接已建立,目标文档已存在。我怀疑是请求格式错误,但未找到嵌套请求相关资料,非嵌套请求可正常执行,请问问题出在哪里?


问题分析与解决方案

1. 请求体格式不匹配

路由代码中判断req.body.connections是否存在,再读取req.body.connections.parents,但当前请求体用了"connections.parents": "test"这种点分隔的扁平键名,Express的JSON解析器不会自动将其解析为嵌套对象,导致req.body.connections为undefined,后续数组push逻辑完全没执行,数据库数据自然无变化。

修正后的请求体:

{
    "connections": {
        "parents": "test"
    }
}

2. 数组push逻辑的潜在问题

即使请求格式正确,当前push逻辑会把传入值整个作为一个元素推入数组:如果传单个值(如"test")结果正常,但如果传数组(如["test1", "test2"]),会得到parents: [["test1", "test2"]]的嵌套数组,不符合预期。

若需支持单个值或批量添加,可修改路由逻辑:

router.patch('/v2/:id', getPerson, async (req, res) => {
    if (req.body.connections) {
        // 处理parents:单个值直接push,数组则展开合并
        if (req.body.connections.parents != null) {
            if (Array.isArray(req.body.connections.parents)) {
                res.person.connections.parents.push(...req.body.connections.parents);
            } else {
                res.person.connections.parents.push(req.body.connections.parents);
            }
        }
        // 处理children逻辑同理
        if (req.body.connections.children != null) {
            if (Array.isArray(req.body.connections.children)) {
                res.person.connections.children.push(...req.body.connections.children);
            } else {
                res.person.connections.children.push(req.body.connections.children);
            }
        }
    }
    try {
        const updatePerson = await res.person.save();
        res.status(200).json({ message: 'Success', data: updatePerson })
    } catch (error) {
        res.status(400).json({ message: error.message })
    }
})

3. 可选:使用Mongoose原子更新提升效率

当前先查询再修改保存的方式,可替换为Mongoose的$push原子操作,减少数据库交互:

router.patch('/v2/:id', async (req, res) => {
    const updateOps = {};
    if (req.body.connections?.parents != null) {
        updateOps['connections.parents'] = req.body.connections.parents;
    }
    if (req.body.connections?.children != null) {
        updateOps['connections.children'] = req.body.connections.children;
    }

    try {
        const updatePerson = await Person.findByIdAndUpdate(
            req.params.id,
            { $push: updateOps }, // $push自动兼容单个值或数组
            { new: true, runValidators: true } // 返回更新后文档,触发Schema验证
        );
        if (!updatePerson) {
            return res.status(404).json({ message: 'Cannot find the person' });
        }
        res.status(200).json({ message: 'Success', data: updatePerson })
    } catch (error) {
        res.status(400).json({ message: error.message })
    }
})

该方式无需getPerson中间件,直接完成查询+更新,效率更高。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 11:06:24