我用猫鼬做这个 API Put 请求正确吗?
Posted
技术标签:
【中文标题】我用猫鼬做这个 API Put 请求正确吗?【英文标题】:Am I doing this API Put request correct with mongoose? 【发布时间】:2016-10-22 00:29:38 【问题描述】:所以我正在使用 mongoose 和 mongodb 并使用 express 路由来做到这一点。
我有一个创建时包含空数组的用户文档-“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】:我建议您使用适当的实体对数据库进行建模,与 User 分开创建 Task 模型并添加对 User 的引用,如下所示:
var TaskSchema = new mongoose.Schema(
user:
type: mongoose.Schema.ObjectId,
ref: 'User'
,
name: String,
importance: String,
completed: Boolean
);
如果你愿意,你也可以在 User 上添加对 Task 的引用:
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 查询参数。
希望对您有所帮助。 :)
【讨论】:
这种情况是否会更好地将所有数据保留在用户的架构中?由于每个用户只有一组任务,不会有很多任务 这是您应该做出的决定。我建议您将它们分开,因为将来随着系统的增长,您可以更灵活地改进任务实体,而无需编辑用户实体。 另外,为了可扩展性,最好将小集合分开而不是大集合。了解更多here 如果您仍然想在用户中嵌入任务(这没有错),我建议您创建像POST /users/:userId/tasks
和 PUT /users/:userId/tasks/:taskId
这样的端点以更清晰。
好的,谢谢。我整天都在想的另一个问题..(这是我第一次制作一个宁静的 api 顺便说一句)但是发出 api 请求的客户端如何知道用户 ID 如果它使用用户,它会不会更好地工作名称而不是 id?以上是关于我用猫鼬做这个 API Put 请求正确吗?的主要内容,如果未能解决你的问题,请参考以下文章
MERN API 请求,不知道如何发出 put 请求并正确更新