Skip to content

Model.bulkWrite fails embedded array update with embedded discriminator and arrayFilters #14978

@lcrosetto

Description

@lcrosetto

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported

Mongoose version

8.7.2

Node.js version

20.18.0

MongoDB server version

8.0.1

Typescript version (if applicable)

No response

Description

When updating an embedded document array with an embedded schema discriminator and filtered positional operator, the operation succeeds when done with Model.updateOne() but throws the following error when the same operation is done by calling Model.bulkWrite():

MongoInvalidArgumentError: Update document requires atomic operators

Steps to Reproduce

In the following script, update will fail with a MongoInvalidArgumentError:

      const conn = mongoose.createConnection(..);

      const embedDiscriminatorSchema = new mongoose.Schema({
        field1: String,
      });

      const embedSchema = new mongoose.Schema({
        field: String,
        key: String,
      }, {discriminatorKey: 'key'});
      embedSchema.discriminator('Type1', embedDiscriminatorSchema);

      const testSchema = new mongoose.Schema({
        testArray: [embedSchema],
      });
      const TestModel = conn.model('Test', testSchema);

      const test = new TestModel({
        testArray: [{
          key: 'Type1',
          field: 'field',
          field1: 'field1',
        }],
      });
      const r1 = await test.save();
      assert.equal(r1.testArray[0].field1, 'field1');

      const field1update = 'field1 update';
      const res = await TestModel.bulkWrite([{
        updateOne: {
          filter: { _id: r1._id },
          update: {
            $set: {
              'testArray.$[element].field1': field1update,
            },
          },
          arrayFilters: [
            {
              'element._id': r1.testArray[0]._id,
              'element.key': 'Type1',
            },
          ],
        },
      }]);
      const r2 = await TestModel.findById(r1._id);
      assert.equal(r2.testArray[0].field1, field1update);

      conn.deleteModel('Test');

However, if the call to bulkWrite() is replaced with updateOne() the operation will succeed:

      const field1update = 'field1 update';
      const res = await TestModel.updateOne(
        { _id: r1._id },
        {
          '$set': {
            'testArray.$[element].field1': field1update,
          },
        },
        {
          arrayFilters: [
            {
              'element._id': r1.testArray[0]._id,
              'element.key': 'Type1'
            },
          ],
        },
      );
      const r2 = await TestModel.findById(r1._id);
      assert.equal(r2.testArray[0].field1, field1update);

Expected Behavior

An update to an embedded array with an embedded schema discriminator should succeed with Model.bulkWrite(), as the same request does when done with Model.updateOne().

Metadata

Metadata

Assignees

No one assigned

    Labels

    confirmed-bugWe've confirmed this is a bug in Mongoose and will fix it.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions