Hello, When I tried a simple transaction example for inserting refer to transactions.test.js. and got an error:
{ MongoError: Cannot create namespace test.as in multi-document transaction.
at ~/test/node_modules/[email protected]@mongodb-core/lib/connection/pool.js:580:63
at authenticateStragglers (~/test/node_modules/[email protected]@mongodb-core/lib/connection/pool.js:503:16)
at Connection.messageHandler (~/test/node_modules/[email protected]@mongodb-core/lib/connection/pool.js:539:5)
at emitMessageHandler (~/test/node_modules/[email protected]@mongodb-core/lib/connection/connection.js:309:10)
at Socket.<anonymous> (~/test/node_modules/[email protected]@mongodb-core/lib/connection/connection.js:452:17)
at emitOne (events.js:115:13)
at Socket.emit (events.js:210:7)
at addChunk (_stream_readable.js:252:12)
at readableAddChunk (_stream_readable.js:239:11)
at Socket.Readable.push (_stream_readable.js:197:10)
at TCP.onread (net.js:589:20)
name: 'MongoError',
message: 'Cannot create namespace test.as in multi-document transaction.',
operationTime: Timestamp { _bsontype: 'Timestamp', low_: 1, high_: 1531118331 },
ok: 0,
errmsg: 'Cannot create namespace test.as in multi-document transaction.',
code: 26,
codeName: 'NamespaceNotFound',
'$clusterTime':
{ clusterTime: Timestamp { _bsontype: 'Timestamp', low_: 1, high_: 1531118331 },
signature: { hash: [Object], keyId: 0 } },
[Symbol(mongoErrorContextSymbol)]: {} }
Here is my code:
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017,localhost:27018,localhost:27019/test?replicaSet=set');
const conn = mongoose.connection;
const Schema = mongoose.Schema;
const schemaA = new Schema({
name: String
});
const schemaB = new Schema({
name: String
});
const A = mongoose.model('A', schemaA);
const B = mongoose.model('B', schemaB);
const a = { name: 'Andrew' };
const b = { name: 'Billy' };
async function run() {
await mongoose.dropDatabase();
const session = await conn.startSession();
await session.startTransaction();
try{
await A.create([a],{session: session});
await B.create([b],{session: session});
await session.commitTransaction();
} catch(e) {
console.log(e);
await session.abortTransaction();
} finally {
session.endSession();
}
return conn.close();
}
run().catch(console.error);
Mongoose version: 5.2.2
mongodb version: v4.0.0
Thanks
I've found out the reason. Just like mongodb document said:
Operations that affect the database catalog, such as creating or dropping a collection or an index, are not allowed in multi-document transactions. For example, a multi-document transaction cannot include an insert operation that would result in the creation of a new collection. See Restricted Operations.
I think Mongoose should fix it by create the collection before saving a document to an non-exist collection.
This is why our transaction docs explicitly create the collection using createCollection(), because unfortunately transactions can't create collections right now.
Unfortunately, I don't think this is something mongoose can do, because we'd have to send at least one extra database operation (at minimum createCollection()) when creating a session. You should just work around this by calling conn.createCollection('as'). Does that work for you?
Most helpful comment
This is why our transaction docs explicitly create the collection using
createCollection(), because unfortunately transactions can't create collections right now.Unfortunately, I don't think this is something mongoose can do, because we'd have to send at least one extra database operation (at minimum
createCollection()) when creating a session. You should just work around this by callingconn.createCollection('as'). Does that work for you?