Skip to content

How to update all fields on Mongoose document update, without putting them one by one

Why change all fields on update?

Sometimes in a project using mongoose we want to update all fields on update, lets say we have a collection of documents with 25 fields, we receive a payload from our client changing multiple fields, we would need to pass the 25 fields to the update query in order to update all the fields on the document, now imagine if we have multiple collection of documents with the same number of fields. We can change this by creating a reusable way to change all the fields in documents

Getting started

First we are going to create a Mongoose schema with multiple fields and an object with all the fields which are immutable, this way we can protect some fields, so we avoid changing them by mistake, for example the _id of the documents

/**
 * Book fields, fields needed to add a new Book
 */
const BookSchema = new Schema(
    {
        _id: {
            type: Schema.ObjectId,
        },
        name: {
            type: String,
            required: true,
        },
        author: {
            type: String,
            required: true,
        },
        published: {
            type: Date,
        },
        isbn: {
            type: String,
        },
        numberPages: {
            type: Number,
        },
        summary: {
            type: String,
        },
        language: {
            type: String,
            default: "EN",
        },
    },
    { collection: "Books", versionKey: "_version" }
);

const Book = mongoose.model("Book", BookSchema);

/**
 * Non editable fields in this object, fields used in update functions
 */
const nonEditableFields = {
    _id: true,
    name: true,
    isbn: true,
};

module.exports = Book;
exports = module.exports;
exports.nonEditableFieldsBook = nonEditableFields;

Now let's create a utility function that accepts an object and the immutable fields and returns a new object excluding the immutable fields

/**
 *
 * @param return object with new values
 * @param {*} object the object we want to check
 * @param {*} nonEditableValues an object with all the non editable values
 */
function getEditedValues(object, nonEditableValues) {
  const finalObject = {};
  const objectCopy = { ...object };
  for (const [key, value] of Object.entries(objectCopy)) {
    if (!nonEditableValues[key]) {
      finalObject[key] = value;
    }
  }
  return finalObject;
}

Next we are going to update all fields on mongo document

/**
 * For this example lets imagine this is the payload we receive from the client
 * containing the new values we want to update on our book collection
 */
const mockBook = {
    _id: "656125fc2b3353ceff96c2c9",
    name: "The best book ever",
    author: "The best author ever",
    published: "2024-03-30T22:42:04.715Z",
    isbn: "0-061-96436-0",
    numberPages: 300,
    summary: "This is the best book ever",
    language: "EN",
}

/**
 * Use utility function to get object excluding no editable fields
 */
const bookNewValues = getEditedValues(
    mockBook,
    nonEditableFieldsBook
);

// Search book by _id and update all editable fields
await Book.updateOne(
    { _id: mockBook._id },
    { ...bookNewValues }
);