question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Document.prototype.set() on nested objects value erase existing previous values

See original GitHub issue

Prerequisites

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

Mongoose version

6.5.1

Node.js version

16.13.1

MongoDB server version

5.0.9

Description

The issue seems to impact the version 6 of mongoose. I recently discovered this bug since i updated to the last version 6 because of a discovered vulnerability that affect older versions to the 6.4…

Steps to Reproduce

Whenever you use the use set with a flattened key/value annotation, it’s seems to work correctly.

await document.set({ "path.subpath": "some value" }).save()

this would work properly assuming that the path potentially contain other subpaths that would not be affected by this change. But if i would write it with a nested object annotation instead then:

await document.set({  path: { subpath: "some value" } }).save()

this would affect the rest of the element potentially contained in path and erase them. The temporary solution that i found here is to manually inject them with a spread operator.

await document.set({  path: { ...document.path, subpath: "some value" } }).save()

but this is not matching the behavior of the $set from MongoDb and in some case it turn out to be very limiting.

Expected Behavior

await document.set({  path: { subpath: "some value" } }).save()

should not erase all the other elements contained within the path key.

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:5 (1 by maintainers)

github_iconTop GitHub Comments

2reactions
vkarpov15commented, Aug 15, 2022

@ramos-ph this is expected behavior. You can set the merge option on set() to merge instead of overwrite. See below changes to @IslandRhythms 's script:

    await entry.set({"fullName.firstName": "Timmy"});
    await entry.save();
    console.log(entry);
    const failure = await Test.findOne();
    failure.set({ fullName: { firstName: 'Timothy'}}, null, { merge: true }); // <-- add merge option here
    await failure.save();
    console.log(failure);
2reactions
IslandRhythmscommented, Aug 8, 2022
const mongoose = require('mongoose');

const testSchema = new mongoose.Schema({
    name: String,
    fullName: {
        firstName: String,
        lastName: String
    }
});

const Test = mongoose.model('Test', testSchema);

async function run() {
    await mongoose.connect('mongodb://localhost:27017');
    await mongoose.connection.dropDatabase();

    await Test.create({
        name: 'Test',
        fullName: {
            firstName: 'Test',
            lastName: 'Testerson'
        }
    });

    const entry = await Test.findOne();

    await entry.set({"fullName.firstName": "Timmy"});
    await entry.save();
    console.log(entry);
    const failure = await Test.findOne();
    await failure.set({ fullName: { firstName: 'Timothy'}});
    await failure.save();
    console.log(failure);

}

run();
Read more comments on GitHub >

github_iconTop Results From Across the Web

Dynamically set property of nested object - javascript
Dynamically sets a deeply nested value in an object. ... @param {boolean} setrecursively - If true, will set value of non-existing path as...
Read more >
Object.assign() - JavaScript - MDN Web Docs
The Object.assign() method copies all enumerable own properties from one or more source objects to a target object.
Read more >
Mongoose v6.8.1: Document
Throws an error if a given path is not populated. Example: const doc = await Model.findOne().populate('author'); doc.$assertPopulated('author'); // does not ...
Read more >
Updating an object value in a nested array - MongoDB
type': type }, { $set: { 'pity.$.totalWishes': 1 } });. Using a positional operator, I'm attempting to set the totalWishes of the specific ......
Read more >
Cloud Firestore Data model - Firebase
Documents can contain subcollections and nested objects, both of which can include ... Note: Cloud Firestore supports a variety of data types for...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found