【问题标题】:Using `mongoose transactions` when saving message in two collections in mongodb在mongodb的两个集合中保存消息时使用`mongoose transactions`
【发布时间】:2021-04-22 04:48:38
【问题描述】:

如果学生向老师发送消息,则消息将保存在 teachersstudents 集合中。同样的情况是当老师给学生发送消息时,他们也保存在teachersstudents这两个集合中。如何在以下代码中应用mongoose transaction 以便将消息保存在两个集合中。我不希望消息将保存在一个集合中而另一个集合中由于错误而不会保存的情况。我正在寻求帮助和线索

const express = require('express');
const mongoose = require('mongoose');
require('dotenv').config();

//const app = express();

// Connect to our Database and handle an bad connections
module.exports.db = mongoose
    .createConnection(process.env.DATABASE, { 
        useNewUrlParser: true, 
        useFindAndModify: false,
        useUnifiedTopology: true, 
        useCreateIndex: true
    }
);




//controller
const db = require('./connection');

const session = db.startSession();
session.startTransaction();

module.exports.sendMessage = (req, res) => {
    
    let {sender, receiver, msg, role} = req.body;
    var hex = /[0-9A-Fa-f]{6}/g;

    sender = (hex.test(sender))? mongoose.Types.ObjectId(sender) : sender;
    receiver = (hex.test(receiver))? mongoose.Types.ObjectId(receiver) : receiver;
    console.log(sender, receiver, msg, 'send');

            if(role === 'tutor') {
                let teacherMessage =  new TeacherMessageSchema.TeacherMessageSchema({
                    contentInfo : {
                        msg : msg
                    },
                    sender : sender
                })

                let studentMessage =  new TeacherMessageSchema.TeacherMessageSchema({
                    contentInfo : {
                        msg : msg
                    },
                    receiver : receiver
                })
        
                db.db.collection('teachers').findOneAndUpdate( 
                    { _id : receiver },
                    { $push: { messages: teacherMessage } },
                    (err, updated) => {
                        console.log(updated, 'vvv');
        
                        updated.value.hashed_password = undefined;
                        updated.value.salt = undefined;
        
                        if(err) {
                            res.status(404).json(err);
                        }
        
                        if (updated) {
                            res.status(200).json(updated.value);

                            db.db.collection('students').findOneAndUpdate( 
                                { _id : sender },
                                { $push: { messages: studentMessage } },
                               
                            );
                        }
                    }, session(session)
                )
        
              
            }
        
        
            if(role === 'student') {
                let studentMessage =  new StudentMessageSchema.StudentMessageSchema({
                    contentInfo : {
                        msg : msg
                    },
                    receiver : receiver
                })

                let teacherMessage =  new TeacherMessageSchema.TeacherMessageSchema({
                    contentInfo : {
                        msg : msg
                    },
                    sender : sender
                })
        
               
        
                db.db.collection('students').findOneAndUpdate( 
                    { _id : sender },
                    { $push: { messages: studentMessage } },
                    (err, updated) => {
                        console.log(updated, 'sss');
            
                        updated.value.hashed_password = undefined;
                        updated.value.salt = undefined;
            
                        if(err) {
                            res.status(404).json(err);
                        }
            
                        if (updated) {
                            res.json(updated.value);
                            db.db.collection('teachers').findOneAndUpdate( 
                                { _id : receiver },
                                { $push: { messages: teacherMessage } },
                               
                            )
                        }
                    }, 
                ), session(session)
            }
}

记录的变量 db

{
  db: NativeConnection {
    base: Mongoose {
      connections: [Array],
      models: [Object],
      modelSchemas: [Object],
      options: [Object],
      _pluralize: [Function: pluralize],
      plugins: [Array]
    },
    collections: {},
    models: {},
    config: { autoIndex: true },
    replica: false,
    options: null,
    otherDbs: [],
    relatedDbs: {},
    states: [Object: null prototype] {
      '0': 'disconnected',
      '1': 'connected',
      '2': 'connecting',
      '3': 'disconnecting',
      '99': 'uninitialized',
      disconnected: 0,
      connected: 1,
      connecting: 2,
      disconnecting: 3,
      uninitialized: 99
    },
    _readyState: 1,
    _closeCalled: false,
    _hasOpened: true,
    _listening: false,
    _connectionOptions: {
      useNewUrlParser: true,
      useFindAndModify: false,
      useUnifiedTopology: true,
      useCreateIndex: true,
      promiseLibrary: [Function: Promise]
    },
    client: MongoClient {
      _events: [Object: null prototype] {},
      _eventsCount: 0,
      _maxListeners: undefined,
      s: [Object],
      topology: [ReplSet],
      [Symbol(kCapture)]: false
    },
    name: null,
    '$initialConnection': Promise { [Circular] },
    db: Db {
      _events: [Object: null prototype],
      _eventsCount: 3,
      _maxListeners: undefined,
      s: [Object],
      serverConfig: [Getter],
      bufferMaxEntries: [Getter],
      databaseName: [Getter],
      [Symbol(kCapture)]: false
    }
  }
}

【问题讨论】:

    标签: javascript mongodb express mongoose transactions


    【解决方案1】:

    我已经在代码中添加了Anytime有错误:

    等待 session.abortTransaction();

    否则(快乐路径)提交更改。

    等待 session.commitTransaction();

    Abort 和 commit 是 Promise 的基本函数,所以我更改了它们用作异步的函数。

    const express = require('express');
    const mongoose = require('mongoose');
    require('dotenv').config();
    
    //const app = express();
    
    // Connect to our Database and handle an bad connections
    module.exports.db = mongoose
        .createConnection(process.env.DATABASE, { 
            useNewUrlParser: true, 
            useFindAndModify: false,
            useUnifiedTopology: true, 
            useCreateIndex: true
        }
    );
    
    
    
    
    //controller
    const db = require('./connection');
    
    
    
    module.exports.sendMessage = async (req, res) => {
        
        const session = await db.startSession();
        session.startTransaction();
    
        let {sender, receiver, msg, role} = req.body;
        var hex = /[0-9A-Fa-f]{6}/g;
    
        sender = (hex.test(sender))? mongoose.Types.ObjectId(sender) : sender;
        receiver = (hex.test(receiver))? mongoose.Types.ObjectId(receiver) : receiver;
        console.log(sender, receiver, msg, 'send');
    
                if(role === 'tutor') {
                    let teacherMessage =  new TeacherMessageSchema.TeacherMessageSchema({
                        contentInfo : {
                            msg : msg
                        },
                        sender : sender
                    })
    
                    let studentMessage =  new TeacherMessageSchema.TeacherMessageSchema({
                        contentInfo : {
                            msg : msg
                        },
                        receiver : receiver
                    })
            
                    db.db.collection('teachers').findOneAndUpdate( 
                        { _id : receiver },
                        { $push: { messages: teacherMessage } },
                        async (err, updated) => {
                            console.log(updated, 'vvv');
            
                            updated.value.hashed_password = undefined;
                            updated.value.salt = undefined;
            
                            if(err) {
                                await session.abortTransaction();
                                res.status(404).json(err);
                                return
                            }
            
                            if (updated) {
                                res.status(200).json(updated.value);
    
                                db.db.collection('students').findOneAndUpdate( 
                                    { _id : sender },
                                    { $push: { messages: studentMessage } },
                                   
                                );
                            }
                        }, session(session)
                    )
            
                  
                }
            
            
                if(role === 'student') {
                    let studentMessage =  new StudentMessageSchema.StudentMessageSchema({
                        contentInfo : {
                            msg : msg
                        },
                        receiver : receiver
                    })
    
                    let teacherMessage =  new TeacherMessageSchema.TeacherMessageSchema({
                        contentInfo : {
                            msg : msg
                        },
                        sender : sender
                    })
            
                   
            
                    db.db.collection('students').findOneAndUpdate( 
                        { _id : sender },
                        { $push: { messages: studentMessage } },
                        async (err, updated) => {
                            console.log(updated, 'sss');
                
                            updated.value.hashed_password = undefined;
                            updated.value.salt = undefined;
                
                            if(err) {
                                await session.abortTransaction();
                                res.status(404).json(err);
                                return;
                            }
                
                            if (updated) {
                                res.json(updated.value);
                                db.db.collection('teachers').findOneAndUpdate( 
                                    { _id : receiver },
                                    { $push: { messages: teacherMessage } },
                                   
                                )
                            }
                        }, 
                        session(session)
                    )
                }
    
                await session.commitTransaction();
    }
    

    【讨论】:

    • 我从未在 Mongoose 5.11 的代码中使用过这个
    • 我有错误:db.startSession is not a function
    • 我有错误:db.startSession is not a function. UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch().
    • 原始代码是否与 db.startSession() 一起使用并在 sendMessage 函数内部移动导致此操作失败?如果是这样的话..这很奇怪。你能在调用 db.startSession 之前记录下 db 的值吗?
    • 我添加了登录db
    猜你喜欢
    • 1970-01-01
    • 2020-01-31
    • 2013-02-13
    • 1970-01-01
    • 1970-01-01
    • 2018-09-29
    • 2019-08-07
    • 2016-05-07
    • 2018-08-21
    相关资源
    最近更新 更多