diff --git a/lib/model.js b/lib/model.js index 3ad42386cb..45c027a1c3 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2619,6 +2619,10 @@ Model.create = async function create(doc, options) { delete options.aggregateErrors; // dont pass on the option to "$save" + if (options.session && !options.ordered && args.length > 1) { + throw new MongooseError('Cannot call `create()` with a session and multiple documents unless `ordered: true` is set'); + } + if (options.ordered) { for (let i = 0; i < args.length; i++) { try { diff --git a/test/docs/transactions.test.js b/test/docs/transactions.test.js index 2a63f07a98..5558d9a103 100644 --- a/test/docs/transactions.test.js +++ b/test/docs/transactions.test.js @@ -344,7 +344,10 @@ describe('transactions', function() { const session = await db.startSession(); session.startTransaction(); - await Character.create([{ name: 'Will Riker', rank: 'Commander' }, { name: 'Jean-Luc Picard', rank: 'Captain' }], { session }); + await Character.create([ + { name: 'Will Riker', rank: 'Commander' }, + { name: 'Jean-Luc Picard', rank: 'Captain' } + ], { session, ordered: true }); let names = await Character.distinct('name', {}, { session }); assert.deepStrictEqual(names.sort(), ['Jean-Luc Picard', 'Will Riker']); @@ -660,4 +663,48 @@ describe('transactions', function() { const { name } = await Test.findById(_id); assert.strictEqual(name, 'bar'); }); + + it('throws error if using `create()` with multiple docs in a transaction (gh-15091)', async function() { + const BookingSchema = new Schema({ + user: mongoose.Types.ObjectId, + slot: mongoose.Types.ObjectId, + bookingFor: String, + moreInfo: String + }); + + // Create models + db.deleteModel(/Test/); + const Booking = db.model('Test', BookingSchema); + + // Define a sample payload + const user = { userId: new mongoose.Types.ObjectId() }; + const payload = { + slotId: new mongoose.Types.ObjectId(), + data: [ + { bookingFor: 'Person A', moreInfo: 'Some info' }, + { bookingFor: 'Person B', moreInfo: 'Other info' } + ] + }; + + const session = await db.startSession(); + session.startTransaction(); + + const bookingData = payload.data.map((obj) => ({ + user: user.userId, + slot: payload.slotId, + bookingFor: obj.bookingFor, + moreInfo: obj.moreInfo + })); + + const bookings = await Booking.create(bookingData, { session, ordered: true }); + assert.equal(bookings.length, 2); + + await assert.rejects( + Booking.create(bookingData, { session }), + /Cannot call `create\(\)` with a session and multiple documents unless `ordered: true` is set/ + ); + + await session.abortTransaction(); + await session.endSession(); + }); });