我用mongoose做这个API Put请求是否正确?

时间:2016-06-20 16:47:35

标签: node.js mongodb api express mongoose

所以我正在使用mongoose和mongodb并表达路由。

我在创建时有一个空数组的用户文档 - “todolist”,我希望能够编辑它以将任务添加到列表中以及编辑这些任务。

现在我认为最好的办法就是让服务器检查req.body是否设置了某些变量以了解我需要编辑的文档部分。

这是正确的方法还是我想为这样的事情创建一个新的API路由,或者我是通过检查客户端的req变量来确定我想在服务器上编辑的内容吗?还有一种更清洁的方法吗?

router.put('/:user_id', function(req, res) {
    User.findById(req.params.user_id, function(err, user){
        if(err){
            res.send(err);
            return err;
        }

        if(req.body.createTask) {
            user.todolist.push({
                "task_name": req.body.task_name,
                "task_importance": req.body.importance,
                "task_completed": false
            })
        }else if(req.body.edit_task){
            if(req.body.edit_task_name) {
                user.todolist[req.body.index].task_name = req.body.new_task_name;
            }else if(req.body.edit_task_importance) {
                user.todolist[req.body.index].task_importance = req.body.new_task_importance;
            }else if(req.body.edit_task_completed) {
                user.todolist[req.body.index].task_completed = true;
            }
        }

        user.save(function(err){
            if(err)
                res.send(err);
            res.json({message: 'User updated'});
        })
    })
});

1 个答案:

答案 0 :(得分:1)

我建议您使用适当的实体对数据库建模,与User分开创建Task模型并添加对User的引用,如下所示:

var TaskSchema = new mongoose.Schema({
  user: {
    type: mongoose.Schema.ObjectId,
    ref: 'User'
  },
  name: String,
  importance: String,
  completed: Boolean
});

如果您愿意,还可以添加对用户任务的引用:

var User = new mongoose.Schema({
  // note this is an array
  todolist: [{
    type: mongoose.Schema.ObjectId,
    ref: 'Task'
  }]
});

这样做,为了简化操作,您应该创建一个pre save hook来自动向用户添加任务:

TaskSchema.pre('save', function(next) {
  if (this.isModified('user') && this.user) {
    // $addToSet will add this document to the user's todolist (if it's not already there)
    User.findOneAndUpdate({_id: this.user}, {$addToSet: {todolist: this}}, function(err, doc) {
      next(err);
    })
  } else {
    next();
  }
});

这样,正确的方法是提供与实体相关的端点。因此,要创建任务,用户应使用正文POST /tasks

请求{ user: '123', name: 'name', ... }
router.post('/tasks', function(req, res) {
  Task.create(req.body, function(err, task) {
    if (err) return res.status(500).send(err);
    return res.status(201).json(task);
  });
});

它将使用我们的预保存挂钩自动将任务添加到用户123。 要编辑任务,只需在任务端点上进行:

router.put('/tasks/:id', function(req, res) {
  Task.findById(req.params.id, function(err, task) {
    if (err) return res.status(500).send(err);
    if (!task) return res.status(404).send('Not Found');

    task.name = req.body.name || task.name;
    task.importance = req.body.importance || task.importance;
    task.completed = true;

    task.save(function(err, task) {
      if (err) return res.status(500).send(err);
      res.status(200).json(task);
    });
  });
});

您不需要编辑用户,因为它只会保留任务参考。

如果您想让用户填充任务数据(而不仅仅是他们的ID),请执行以下操作:

router.get('/users', function(req, res) {
  User.find({}).populate('todolist').exec(function(err, users) {
    ...
  });
});

对于上述类似的查询,我建议您使用像querymen这样的库,它将查询字符串(例如GET /users?q=Some+Search&limit=10&page=2)解析为MongoDB查询参数。

希望它有所帮助。 :)