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

基于NodeJS Joi实现仅提交修改后数据至MongoDB的方法

解决方案

要实现仅提交用户修改过的字段到数据库,核心思路是先获取用户的原始数据,和请求 payload 对比后筛选出差异字段,再进行验证与更新。具体步骤如下:

1. 查询用户原始数据

在验证请求 payload 前,先从数据库获取该用户的当前数据,作为对比基准:

const originalUser = await getUserById(id); // 请确保你有对应的查询方法
if (!originalUser) {
  res.status(404).json({ message: `user ${id} not found` });
  return;
}

2. 筛选修改过的字段

遍历请求 payload 的所有键,和原始数据逐一对比,只保留值不同的字段:

const updatedFields: Partial<IUser> = {};
Object.keys(req.body).forEach(key => {
  // 处理类型兼容问题
  if (req.body[key] !== originalUser[key as keyof IUser]) {
    updatedFields[key as keyof IUser] = req.body[key];
  }
});

// 若没有任何修改,直接返回提示
if (Object.keys(updatedFields).length === 0) {
  res.json({ message: `user ${id} no changes to update`, user: originalUser });
  return;
}

3. 验证并更新筛选后的字段

用你的 Joi Schema 验证筛选后的字段,确认合法后提交到数据库更新:

try {
  await userEditSchema.validateAsync(updatedFields);
} catch (error) {
  res.status(400).json({ error });
  return;
}

try {
  const user = await updateUserById(id, updatedFields);
  res.json({ message: `user ${id} updated`, user });
} catch (error) {
  res.status(500).json({ error });
}

整合后的完整代码

优化后的 updateUser 函数如下:

const updateUser = async (req: MyR, res: Response): Promise<void> => {
  const { id } = req.params;

  try {
    // 获取原始用户数据
    const originalUser: IUser | null = await getUserById(id);
    if (!originalUser) {
      res.status(404).json({ message: `user ${id} not found` });
      return;
    }

    // 筛选差异字段
    const updatedFields: Partial<IUser> = {};
    Object.keys(req.body).forEach(key => {
      if (req.body[key] !== originalUser[key as keyof IUser]) {
        updatedFields[key as keyof IUser] = req.body[key];
      }
    });

    if (Object.keys(updatedFields).length === 0) {
      res.json({ message: `user ${id} no changes to update`, user: originalUser });
      return;
    }

    // 验证字段合法性
    await userEditSchema.validateAsync(updatedFields);

    // 执行数据库更新
    const user = await updateUserById(id, updatedFields);
    res.json({ message: `user ${id} updated`, user });
  } catch (error) {
    if ((error as Error).name === 'ValidationError') {
      res.status(400).json({ error });
    } else {
      res.status(500).json({ error });
    }
  }
};

额外说明

  • 若用户数据包含嵌套对象,需要递归对比字段值,上述代码仅处理顶层字段;
  • 对于数组类型字段,浅对比可能不准确,可使用 lodash.isEqual 进行深比较;
  • 你的 Joi Schema 中所有字段均为可选,刚好适配筛选后可能只有部分字段的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 08:25:35