Does .save() on a Partially Loaded Mongoose Document Affect Non-Projected Fields?

Hello,

I’m working with Mongoose in a Node.js application and have encountered a situation where I’m not entirely sure about the expected impact of using .save() on a document that has been partially loaded with a projection.

Here’s a simple code snippet illustrating my scenario:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const mySchema = new Schema({
  field1: String,
  field2: String,
  field3: String
  // ... other fields ...
});

const MyModel = mongoose.model('MyModel', mySchema);

// Finding a document with a projection
MyModel.find({}, 'field1 field2').exec(function (err, docs) {
  if (err) {
    // handle error
    console.error(err);
  } else {
    let doc = docs[0];
    // Update some of the projected fields
    doc.field1 = 'new value for field1';

    // Save the document
    doc.save(function (saveErr) {
      if (saveErr) {
        // handle save error
        console.error(saveErr);
      } else {
        console.log('Document saved successfully.');
      }
    });
  }
});

In this example, I’m querying for documents but only projecting field1 and field2. After modifying one of these projected fields, I use .save() to update the document.

My question is: What happens to the other fields (like field3) that were not included in the projection? Will they remain unchanged in the database, or does saving the partial document in some way affect these non-projected fields?

I haven’t explicitly set any strict options in my schema, and I’m observing that the non-projected fields seem to remain unchanged. However, I want to confirm if this is the expected behavior and if it’s safe to rely on this in production environments.

Thank you

Hi @Amit,

Welcome to the MongoDB Community forums!

When you use a projection (specifying fields to retrieve) with find() or similar operations, only the specified fields are retrieved from the database. When you subsequently modify and save the document, only the fields you’ve explicitly modified will be updated in the database.

To validate this behavior, I reproduced a code snippet locally:

const mongoose = require('mongoose');
const userSchema = new mongoose.Schema({
    name: {
        type: String,
        required: true
    },
    sname: {
        type: String,
        required: true
    },
    age: Number,
});

mongoose.connection.on('connected', () => {
    console.log("Connection established successfully");
});

const UserModel = mongoose.model("User", userSchema);
const url = MONGODB_CONNECTION_STRING;

mongoose.connect(url, { useNewUrlParser: true, useUnifiedTopology: true })
    .then(async () => {
        await run();
        mongoose.disconnect();
    })
    .catch(error => {
        console.error("Error connecting to the database:", error);
    });

async function run() {
    try {
        let user = await UserModel.create({
            name: "Ryan",
            sname: "Dahl",
            age: 40,
        });

        console.log(`Inserted user: ${user}`);

        console.log("Finding one user, projecting age, and updating it:-");
        user = await UserModel.findOne({},"age");
        if (user) {
            user.age = 38;
            await user.save();
            console.log(user);
        } else {
            console.log("User not found");
        }
        user = await UserModel.findOne()
        console.log(`Current and updated data: ${user}`);
    } catch (error) {
        console.error("Error in run function:", error);
    }
}

And got the following output:

Connection established successfully

Inserted user: {
  _id: 6555b61182fa5e2cfdbed7a6,
  name: 'Ryan',
  sname: 'Dahl',
  age: 40,
  __v: 0
}

Finding one user, projecting age, and updating it:- 
{ _id: 6555b61182fa5e2cfdbed7a6, age: 38 }

Current and updated data: {
  _id: 6555b61182fa5e2cfdbed7a6,
  name: 'Ryan',
  sname: 'Dahl',
  age: 38,
  __v: 0
}

In your scenario, after retrieving a document with a projection (including only field1 and field2), modifying field1, and then saving it, Mongoose will only update the fields that were modified (field1 in this case). Other fields like field3 that were not part of the projection and not modified will remain unchanged in the database and this is the expected behavior in Mongoose.

Note: Please thoroughly test and update the query as per your requirements before using it in your application.

Best regards,
Kushagra

2 Likes

Thank you Kushagra for the informative and helpful response!

2 Likes

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.