目前我正在尝试在api通话中更新两个不同的用户架构。
第一个架构记录在用户架构中,我们给它命名= Tom 第二个模式是为应用注册的其他用户,我们给它命名= John
架构代码
schema.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var bcrypt = require('bcrypt-nodejs');
var UserSchema = new Schema({
name: String,
username: { type: String, required: true, index: { unique: true }},
password: { type: String, required: true, select: false },
followers: [{ type: Schema.Types.ObjectId, ref: 'User'}],
following: [{ type: Schema.Types.ObjectId, ref: 'User'}],
followersCount: Number,
followingCount: Number
});
module.exports = mongoose.model('User', UserSchema);
api名称是' / follow /:user_id',我想要实现的是。每当用户Tom关注其他用户(如John)时,Tom的关注字段将会更新以及John的关注者字段。
我当前的尝试(req.decoded.id是登录用户)
api.js
// The first way
apiRouter.post('/follow/:user_id', function(req, res) {
User.findOneAndUpdate(
{
_id: req.decoded.id,
following: { $ne: req.params.user_id }
},
{
$push: { following: req.params.user_id},
$inc: { followingCount: 1}
},
function(err, currentUser) {
if (err) {
res.send(err);
return;
}
console.log(currentUser);
});
User.findOneAndUpdate(
{
_id: req.params.user_id,
followers: { $ne: req.decoded.id }
},
{
$push: { followers: req.decoded.id },
$inc: { followersCount: 1}
}, function(err, user) {
if(err) {
res.send(err);
return;
}
res.json({
message: "Successfully followed"
});
}
)
});
//Second way
apiRouter.post('/follow/:user_id', function(req, res) {
// find a current user that has logged in
User.update(
{
_id: req.decoded.id,
following: { $ne: req.params.user_id }
},
{
$push: { following: req.params.user_id},
$inc: { followingCount: 1}
},
function(err) {
if (err) {
res.send(err);
return;
}
User.update(
{
_id: req.params.user_id,
followers: { $ne: req.decoded.id }
},
{
$push: { followers: req.decoded.id },
$inc: { followersCount: 1}
}
), function(err) {
if(err) return res.send(err);
res.json({ message: "Successfully Followed!" });
}
});
});
两者都有问题,
第一种方式:问题是,“无法设置已发送的标头”,因为在一次api调用中有两个单独的mongoose查询,它会响应两次' s为什么我收到了这个错误。
第二种方式:问题是,登录用户(Tom)的跟随字段会更新,而其他用户的关注者字段(John)返回null。我控制记录这两个值,并使用POSTMAN chrome app测试它。
把你的想法借给我!
答案 0 :(得分:1)
第二种方式是正确的(可以改进并行运行它们)我猜问题是在另一个地方。我不知道你正在使用哪个框架,但我想字段_id
来自mongoDB并且是ObjectId
,看起来decode.id可以是objectId,而来自来自请求当然只是一个字符串。所以我猜它是空的,因为它找不到任何有该字符串的用户。
尝试使其成为该字符串中的objectId(在第二个查询中请求req.params.user_id
)
答案 1 :(得分:1)
你采取的第一条路线似乎没问题。
但是,正如@cdbajorin所提到的那样,错误"无法发送已发送的标头"与mongoose无关,但事实上你已经在向客户端发送响应之后尝试设置标题。 (see this lovely answer)
我的建议是在发送响应之前确保两个数据库调用都成功。
在这种情况下,您可能还需要查看two phase commit,因为MongoDB不支持传统的数据库事务,而且您一次只能更新两个文档。如果由于某种原因,数据库调用失败,则应采取恢复到稳定状态的过程。
答案 2 :(得分:0)
第一种方式可以通过两种方式得到改善。一个是在更新后续字段的回调中更新关注者字段。另一种方法是使用async-waterfall。我建议使用async-waterfall(npm async-waterfall)。