我有一个简单的应用程序,它使用NodeJS + Express + MongoDB(mongoose)与API构建进行通信。我的问题被提到了API方面。
我使用此架构在MongoDB中存储用户配置:
{
user: Number,
name: String,
lists: {
invoices: {
year: Number,
orderCol: String,
order: Number
}
}
}
}
每个用户只有一个文档,用于存储我的前端应用程序使用的值,以显示按年份排序和筛选的发票列表。
我需要更新文档,但每次只需要更新一个属性。例如,通过调用API,我希望能够将user.lists.invoices.year
更改为2017,而无需更改order
& orderCol
。
我向API发送了三个值:列表类型(invoices
),要更改的属性(year
)和要设置的值(2017
)。
// PUT request with this payload
{
list: 'invoices',
property: 'year',
value: 2017
}
我正在使用user
字段进行查询。
router.put('/lists/:usr', (req, res, next) => {
var listData = req.body; // listData.list, listData.property, listData.year
var usr = req.params.usr;
Config.findOneAndUpdate(
{ user: usr },
{ $set: { ??? } },
{ new: true, upsert: true },
(err, config) => {
if (err) return next(err);
res.json({ data: config });
}
)
})
请注意可能的重复:我在Google和SO中的搜索总是引导我$
运营商,但我不知道这是否是解决方案,无论如何我不知道如何使用在这种情况下。
也许只是我没有设计正确的架构,在这种情况下我会提出任何建议。
答案 0 :(得分:1)
我对整个API结构不太确定,但我认为我们可以通过以下代码解决这个特定问题:
Config.findOne({ user: usr }, (err, config) => {
if (err) return next(err);
// Be careful if config.lists[list] or config.lists[list][property] can be undefined
config.lists[list][property] = value;
// this might be needed
// config.markModified('lists.' + list + '.' + property);
config.save(err => {
if (err) return next(err);
res.json({ data: config });
});
});
我们总是可以先找到文档,直接应用一些修改,然后再将其保存到数据库中,而不是使用更新功能。
此外,这种更新API似乎有点不寻常,我无法判断它是否适合你。无论如何,我建议添加一个验证中间件。这样简单的事情可能会有所帮助:
function validator(req, res, next) {
const fields = ['list', 'property', 'value'];
if (!fields.every(field => req.body[field] !== undefined)) {
return res.status(400).json({ error: 1, msg: fields.join(', ') + ' are required' });
}
if (['invoices', 'interests', 'etc'].indexOf(req.body.list) === -1) {
return res.status(400).json({ error: 1, msg: 'list is invalid' });
}
// More validations here...
next();
}
上面的示例不能很好地扩展(可能应该编写一个更通用的验证器中间件以在API之间共享)但希望它仍然可以提供一个有用的想法。