Search code examples
node.jsmongodbexpressmongoosedata-migration

unable to update the createdAt property in mongoose?


Hello All expert ,

Might be question seem duplicate but mine business case is little different, Please, bear with me.

I am working old Schema defined by other developer where createdAt and updatedAt properties are missing. so I have updated the schema by adding the { timestamps: true }. whenever I am creating new document then there is no problem. it is working as expected but existing/old documents are there so I am trying to add createdAt properties by writing separate script and reading created time from _id property like _id.getTimestamp(). I am able to extract created time from _id but unable to add createdAt property in existing document. old documents/data is very crucial but business is expecting to add createdAt propery to old document.

I am using mongoose NPM library and version is : "mongoose": "^5.9.16",

Schema sample as below:

    const mongoose = require("mongoose");
    const Schema = mongoose.Schema;
    
    const profileSchema = new Schema(
      {
        name: {
          type: String,
          required: true
        },
        profile_number: {
          type: Number
        },
        view: {
          type: String
        },
     
      },
      { timestamps: true }
    );
module.exports = mongoose.model("profile", profileSchema, "profile");

Script to add createdAt property with extracting the timestamp from _id

    const mongoose = require("mongoose");
    const Profile= require("../../models/Profile/ProfileModel");
    
    /****
     * * Fetch all Portfolios List
     * */
    exports.getAllProfileList = async (req, res, next) => {
      try {
    
        const profileResult = await Profile.find({},{_id:1}).exec(); //return all ids
        const timeStampExtract = await profileResult.map(item => {
          console.log("Item is:", item._id.getTimestamp());
// trying to update createdAt time by extacting item._id.getTimestamp()
          Profile.findOneAndUpdate(
            { _id: item._id },
            { $set: { createdAt: item._id.getTimestamp() } },
            { upsert: true }
          )
            .then(res => console.log("Response:"))
            .catch(error => console.log("Error is:", error.message));
          return item._id.getTimestamp();
        });
   
        if (!profileResult ) {
          return res
            .status(400)
            .json({ message: "Unable to find profile list", statusCode: 400 });
        }
        res
          .status(200)
          .json({ totalCount: profileResult.length, data: timeStampExtract });
      } catch (error) {
        logger.error(error.message);
        return res.status(500).json({ message: error.message, statusCode: 500 });
      }
    };

is By-default createdAt is immutable ?

Could some someone help with it? It will be great help.

Thanks to All experts


Solution

  • Since some of the documents were created when the timestamps option was set to false (this is the default value) mongoose will not know those timestamps. Hence, item._id.getTimestamp() will return undefined.

    What you can do, is to recreate the entries where createdAt does not exist. Mongoose will then automatically generate the timestamps and set them to the current timestamp, if the option is enabled:

        const profilesWithoutCreated = await Profile.find({createdAt: {$exists: false}}).exec();
        const timeStampExtract = [];
        let newProfile;
        for (const profile of profiles) {
           newProfile = new Profile(profile);
           newProfile.createdAt = profile._id.getTimestamp();
           const savedProfile = await newProfile.save();
           timeStampExtract.push(savedProfile._id.getTimestamp());
        }