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?