在api调用中更新2个猫鼬模式 [英] Updating 2 mongoose schemas in an api call

查看:70
本文介绍了在api调用中更新2个猫鼬模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当前,我正在尝试在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调用中有两个单独的猫鼬查询,它两次响应,这就是为什么我收到该错误.

第二种方法:问题是,已登录用户(Tom)的关注字段被更新,而另一个用户的关注者字段(John)返回null.我在控制台上记录了两个值,并使用POSTMAN chrome应用程序对其进行了测试.

把你的想法借给我!

解决方案

您采取的第一条路线似乎不错.

但是,正如@cdbajorin所提到的那样,错误无法发送已发送的报头"与猫鼬无关,而是事实是您已经在向客户端发送响应之后尝试设置报头. (看到这个可爱的答案)

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

您可能还想研究两阶段提交在这种情况下,因为MongoDB不支持传统的数据库事务,并且您要一次更新两个文档.如果由于某种原因两个数据库调用均失败,则应采用恢复到稳定状态的过程.

Currently I'm trying to update Two different User Schema's in an api call.

The first schema is logged in user schema, we give it a name = Tom The second schema is other users who signup for the app, we give it a name = John

The schema code

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);

The api name is '/follow/:user_id', what I want to achieve is . Whenever user Tom follows other user's like John, Tom's following field will be updated as well as John's follower field.

My current attempt (req.decoded.id is the logged in user)

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!" });
                }

        });
});

Both have problems,

The first way: The problem is, 'Can't set headers that already sent', because of the two separate mongoose query in one api call, it response twice that's why I get that error.

The second way: The problem is, the following field of logged in user(Tom) gets updated while the other user's followers field (John) return null. I console log both value and as well test it with POSTMAN chrome app.

Lend me your thoughts fellas!

解决方案

The first route you took seems to be fine.

However, as @cdbajorin mentioned, the error "can't send headers that already sent" has nothing to do with mongoose but the fact that you're trying to set the header after sending a response to the client already. (see this lovely answer)

My suggestion would be to make sure that both database calls are successful before you send a response.

You may also want to look into a two phase commit in this situation, as MongoDB does not support traditional DB transactions and you're updating two documents, one at a time. If for some reason either database call fails, a procedure to recover to a stable state should be taken.

这篇关于在api调用中更新2个猫鼬模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆