我有一个简单的应用程序,它与使用 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 发送三个值:列表类型 (发票
)、要更改的属性 (年份
) 和要设置的值 (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 中的搜索总是引导我到 $
运算符,但我不知道这是否是这个问题的解决方案,无论如何我也不知道在这种情况下如何使用它。
也许只是我没有设计正确的架构,在这种情况下,我会感谢任何建议。
最佳答案
我不太确定整个 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 之间共享),但希望它仍然可以提供有用的想法。
关于node.js - 更新 Mongoose 模式中的动态字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44114684/