mysql - 使用 Express.js 和 mysql 处理 PATCH 请求

标签 mysql node.js api express

假设我有以下路线:

POST/users 其中所有字段都是必需的,这会向我的数据库添加一个用户,假设这个用户获得了 1id

{
    "firstName": "FirstName",
    "lastName": "LastName",
    "email": "email@example.com",
    "address": "address"
}

我还有路由 GET/users,它显示了数据库中的所有用户。

[
    {
        "id": 1,
        "firstName": "FirstName",
        "lastName": "LastName",
        "email": "email@example.com",
        "address": "address"
    }
]

现在,我正在尝试使用一条路径来更新特定用户,PATCH/users

我想让所有字段都可选,并且只发送我通过 PATCH 路由更新的字段,id 将从 JWT token 中解码。

重要的是要注意数据显示在前端的表单中,我想更新表单但只发送从表单更新的值而不是整个表单。实际表单有 30 多个字段。

我知道如果我使用 PUT 请求,我可以发送表单中的所有值并执行以下操作:

editUser = async ({ firstName, lastName, email, address }) => {
    let sql = `UPDATE users
    SET firstName = ?, lastName = ?, email=?, address=? WHERE id = ?`;

    const result = await query(sql, [firstName, lastName, email, address, userId ]);

    return result;
}

现在,假设我只更新表单中的电子邮件并发送它。例如: 补丁/用户

{
    "email":"email@gmail.com"
}

这也很简单:

editUser = async ({ email }) => {
    let sql = `UPDATE users
    SET email = ? WHERE id = ?`;

    const result = await query(sql, [email, userId]);

    return result;
}

上面的方法是仅PATCH 电子邮件的好方法。

所以现在当我执行 GET/users 时,我得到以下信息:

[
    {
        "id": 1,
        "firstName": "FirstName",
        "lastName": "LastName",
        "email": "email@gmail.com",
        "address": "address"
    }
]

但是我如何处理我不知道哪些 key 被发送到后端的不同情况?例如,一组可以如下所示: 补丁/用户

{
    "lastName": "updatedLastName"
    "email":"email@gmail.com"
}

以上在实践中可以是对象中所有不同键的任意组合。根据键生成自定义查询并仅使用需要更新的列更新表中的行的好方法是什么?

最佳答案

我没有比这些更好的主意了:

使用 forEach:

const buildPatchQuery = (table, id, data) => {
    if (Object.keys(data).length === 0) return null; // Or return what you want
    let sql = `UPDATE ${table} SET`;
    Object.entries(data).forEach(([key, value]) => {
        const valueToSet = typeof data[key] === 'string' ? `'${value}'` : value;
        sql += ` ${key}=${valueToSet},`;
    });
    sql = sql.slice(0, -1); // Remove last ","
    sql += ` WHERE id=${id};`;
    return sql;
}

有 map :

const buildPatchQuery = (table, id, data) => {
    if (Object.keys(data).length === 0) return null; // Or return what you want
    let query = `UPDATE ${table} SET `;
    query += Object.keys(data).map((key) => {
        const valueToSet = typeof data[key] === 'string' ? `'${data[key]}'` : data[key];
        return `${key}=${valueToSet}`;
    }).join(', ');
    return query + ` WHERE id=${id};`;
}

减少:

const buildPatchQuery = (table, id, data) => {
    if (Object.keys(data).length === 0) return null; // Or return what you want
    let query = `UPDATE ${table} SET`;
    query += Object.entries(data).reduce((acc, [key, value], index, array) => {
        const valueToSet = typeof data[key] === 'string' ? `'${value}'` : value;
        const optionalComma = index < array.length-1 ? ',' : '';
        return `${acc} ${key}=${valueToSet}${optionalComma}`;
    }, '');
    return query + ` WHERE id=${id};`;
}

通过使用您的 SQL 库:

const buildPatchQuery = (table, id, data) => {
    if (Object.keys(data).length === 0) return null; // Or return what you want
    let sql = `UPDATE ${table} SET`;
    const newValues = [];
    Object.entries(data).forEach(([key, value]) => {
        sql += ` ${key}=?,`;
        newValues.push(value);
    });
    sql = sql.slice(0, -1); // Remove last ","
    sql += ' WHERE id=?;';
    newValues.push(id);
    return query(sql, newValues);
}

测试:

console.log(buildPatchQuery('users', 1, {name: 'toto', email: 'truc', age: 18}));
console.log(buildPatchQuery('users', 1, {name: 'toto'}));
console.log(buildPatchQuery('users', 1, {}));

(未通过 SQL 库测试)

但是,请务必检查 data 对象并通过检查身份验证和权限来保护您的路由,以避免 SQL 注入(inject)或任何黑客攻击!

关于mysql - 使用 Express.js 和 mysql 处理 PATCH 请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68987700/

相关文章:

javascript - Nodejs Express 4.0 post json对象

node.js - Google Cloud 跟踪 自定义跟踪只能运行几次

node.js - Array.forEach/.map 与 path.resolve 一起使用时返回错误

php - 关闭 mysqli 连接会产生 : Couldn't fetch mysqli_result

php - MySQL特殊字符问题

javascript - Node.js - 在 Windows 上运行包时无法读取 null 的属性 'toString'

java - 如何使用 android 的 MediaRecorder 检测文件何时达到其最大大小?

api - 超过 Youtube Data API 配额

php - 在mysql中检索具有不同ID的多行

android - 使用 Android 连接到远程 MySQL 数据库