Node.js 更新Mongoose模式中的动态字段

Node.js 更新Mongoose模式中的动态字段,node.js,mongodb,mongoose,Node.js,Mongodb,Mongoose,我有一个简单的应用程序,它通过NodeJS+Express+MongoDB(mongoose)与API构建通信。我的问题是关于API方面的 我使用此模式在MongoDB中存储用户配置: { user: Number, name: String, lists: { invoices: { year: Number, orderCol: String,

我有一个简单的应用程序,它通过NodeJS+Express+MongoDB(mongoose)与API构建通信。我的问题是关于API方面的

我使用此模式在MongoDB中存储用户配置:

{
    user: Number,
        name: String,
        lists: {
            invoices: {
                year: Number,
                orderCol: String,
                order: Number
            }
        }  
    }
}
每个用户只有一个文档,用于存储我的前端应用程序用于显示按年份排序和筛选的发票列表的值

我需要更新文档,但每次只需更新一个属性。例如,通过调用API,我希望能够将
user.list.invoices.year
更改为2017年,而无需更改
order
&
orderCol

我将向API发送三个值:列表类型(
invoices
)、要更改的属性(
year
)和要设置的值(
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之间共享),但希望它仍然能提供一个有用的想法。

它对我来说非常适合。谢谢你的解释。
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();
}