Skip to content

Pre validate: is not triggert on all sub documents when set via _.set() with a nested path #14591

@MarijnMensinga

Description

@MarijnMensinga

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.3.4

Node.js version

v20

MongoDB server version

5.0

Typescript version (if applicable)

5.4.5

Description

If I have a multi nested document like this: doc = {a: {b: {c: {d: {e: string} } } } }
And then I change a value via await doc._set({'a.b.c.d.e': 'value'}).save() the value is saved correctly in the nested e subDocument. But during the saving process not all the pre('validate', () => ..) hooks get triggered.

Only on the first (a) and second subdocument (b) the pre validate hook is triggered.

Steps to Reproduce

const createSchema = (path,subSchema) => {
    const schema = new Schema({[path]: subSchema})
    schema.pre('validate', function () {
        console.debug(' - pre.validate ::',path)
    })
    schema.pre('save', function () {
        console.debug(' - pre.save ::',path)
    })
    return schema
}

const e = createSchema('e', {type: String})
const d = createSchema('d', {type: e})
const c = createSchema('c', {type: d})
const b = createSchema('b', {type: c})
const a = createSchema('a', {type: b})

const NestedModelHooksTestModel = model('NestedModelHooksTest', a)

// Variant 1
console.debug('Creating doc: {a: {b: {c: {d: {e: "SomeDate"}}}}}')
const newData = {a: {b: {c: {d: {e: new Date().toString()}}}}}
const doc = await new NestedModelHooksTestModel(newData).save()

// Variant 2
console.warn('Updating via new value: {a: {b: {c: {d: {e: "Some override value"}}}}}')
doc.set({a: {b: {c: {d: {e: "Some override value"}}}}})
await doc.save()

// Variant 3
console.warn('Updating via doc: doc.a.b.c.d.e = \'updated nested value 2\'')
doc.a.b.c.d.e = 'updated nested value 2'
await doc.save()

// Variant 4
console.warn('Updating via set: {\'a.b.c.d.e\': \'updated nested value\'}')
doc.set({'a.b.c.d.e': 'updated nested value'})
await doc.save()

Expected Behavior

For every variant I expected the following output:

 - pre.validate :: a
 - pre.validate :: b
 - pre.validate :: c
 - pre.validate :: d
 - pre.validate :: e
 - pre.save :: e
 - pre.save :: d
 - pre.save :: c
 - pre.save :: b
 - pre.save :: a

This is indeed the output for variants 1, 2 and 3

But when using doc.set({'a.b.c.d.e': 'updated nested value'}), aka variant 4, the value is saved correctly but not all the pre validate hooks are triggered:

 - pre.validate :: a
 - pre.validate :: b
 - pre.save :: e
 - pre.save :: d
 - pre.save :: c
 - pre.save :: b
 - pre.save :: a

I was expecting to see the following pre validate hooks get triggered as well:

 - pre.validate :: c
 - pre.validate :: d
 - pre.validate :: e

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