【问题标题】:Updating 2 mongoose schemas in an api call在 api 调用中更新 2 个猫鼬模式
【发布时间】:2015-04-13 00:24:14
【问题描述】:

目前我正在尝试在一个 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 的 following 字段以及 John 的 follower 字段都会更新。

我当前的尝试(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 查询,它响应两次,这就是我收到该错误的原因。

第二种方式:问题是,登录用户(Tom)的following字段被更新,而其他用户(John)的followers字段返回null。我控制台记录这两个值并使用 POSTMAN chrome 应用程序对其进行测试。

兄弟们,把你的想法借给我!

【问题讨论】:

  • “其他用户的followers字段(John)返回null”是什么意思?
  • “无法设置已发送的标头”与猫鼬或您的查询无关。这与多次调用res.send()res.json() 有关。第一个示例中可能发生的唯一方法是顶部的findOneAndUpdate 有错误。

标签: node.js mongodb mongoose mean-stack


【解决方案1】:

第二种方法是正确的(可以改进并行运行它们)我猜问题出在另一个地方。我不知道您使用的是哪个框架,但我猜该字段 _id 来自 mongoDB 并且是 ObjectId 并且看起来 decoded.id 可以是 objectId 而来自请求的那个当然是只是一个字符串。所以我猜它是空的,因为它没有找到任何具有该字符串的用户。

尝试从该字符串中将其设为 objectId(在第二个查询中引用 req.params.user_id

【讨论】:

    【解决方案2】:

    您走的第一条路线似乎还不错。

    但是,正如@cdbajorin 所提到的,错误“无法发送已发送的标头”与猫鼬无关,而是您在向客户端发送响应后尝试设置标头的事实。 (see this lovely answer)

    我的建议是在发送响应之前确保两个数据库调用都成功。

    在这种情况下,您可能还想查看two phase commit,因为 MongoDB 不支持传统的数据库事务,并且您要更新两个文档,一次一个。如果由于某种原因任一数据库调用失败,则应采取恢复到稳定状态的过程。

    【讨论】:

      【解决方案3】:

      第一种方式可以通过两种方式进行改进。一种是在更新关注字段的回调中更新关注者字段。另一种方法是使用异步瀑布。我建议使用 async-waterfall(npm async-waterfall)。

      【讨论】:

      猜你喜欢
      • 2018-03-05
      • 1970-01-01
      • 1970-01-01
      • 2015-04-11
      • 2022-01-12
      • 2020-05-03
      • 2015-09-09
      • 2023-03-04
      • 1970-01-01
      相关资源
      最近更新 更多