mysql - 使用 Express.js 和 mysql 处理 PATCH 请求
问题描述
假设我有以下路线:
POST /users
其中所有字段都是必需的,这会将用户添加到我的数据库中,假设这个用户获得id
了1
{
"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 令牌中解码。
重要的是要注意数据显示在前端的表单中,我想更新表单,但只发送从表单而不是整个表单更新的值。实际的表单有 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;
}
现在,假设我只更新表单中的电子邮件并发送它。例如:
PATCH /users
{
"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"
}
]
但是如何处理我不知道哪些密钥被发送到后端的不同情况?例如,一组可以如下:
PATCH /users
{
"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;
}
用地图:
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 注入或任何黑客攻击!
推荐阅读
- python - 使用 pandas dataframe.hist api 使刻度不可见 pandas hist 图
- android - Android中的图像压缩?
- angular - 如何解决,Angular:错误类型错误:无法读取未定义的属性“名称”
- swift - 使用 Alamofire 时,tuple 类型的 value has no member validate 是什么意思?
- c# - 带有类的 C# Lambda 表达式
- java - 连接到 Web 服务的 Java 桌面应用程序 - oAuth
- flutter - 颤振堆栈大小到兄弟
- r - 评估错误:& 未为“日期”对象定义
- javascript - jQuery 下载 HTML
- xamarin - 如何在 Xamarin.Android 中更改 ListView 项目文本颜色?