0

I have my mongoose schema defined as follows.

mongoose.Schema({
    "url": String,
    "translations": [
        {
            "targetLang": String,
            "source": String,
            "target": String
        }
    ],
}, { versionKey: false });

I updated my schema to include createdAt and updatedAt with the new schema looking as:

mongoose.Schema({
    "url": String,
    "translations": [
        {
            "targetLang": String,
            "source": String,
            "target": String,
            "createdAt": { type: Date, default: Date.now },
            "updatedAt": { type: Date, default: Date.now }
        }
    ],
}, { versionKey: false });

So when new documents are created, the createdAt and updatedAt is auto-populated, as expected. How can I have the old documents with the new key createdAt and updatedAt. Is there any way?

Note: I am okay with the old documents to have the current or any previous date. But I want all of them to have a date.

Amanda
  • 2,013
  • 3
  • 24
  • 57
  • You can check the answer to this question to extract the creation date from the ObjectId of the document: https://stackoverflow.com/questions/7327296/how-do-i-extract-the-created-date-out-of-a-mongo-objectid – makmonty Aug 24 '20 at 13:16
  • @makmonty I am okay with the old documents to have any old date and not necessarily looking to have the exact creation date because the array would have been updated multiple times. – Amanda Aug 24 '20 at 13:19
  • I don't think it's possible with one single command, you'll have to do some scripting to achieve this. – makmonty Aug 24 '20 at 13:28

1 Answers1

1

You'll need to update them manually, from mongoshell for example:

{
    const toUpdate = db.getCollection('collection').find({
        $or: [
            { 'translations.createdAt': null },
            { 'translations.updatedAt': null }
        ]
    });

    toUpdate.forEach(doc => {
        const timestamp = doc._id.getTimestamp();
        doc.translations.createdAt = timestamp;
        doc.translations.updatedAt = timestamp;
        
        db.getCollection('collection').updateOne({ _id: doc._id }, { $set: doc });
    });
}
domenikk
  • 1,723
  • 1
  • 10
  • 12
  • The problem @Amanda has is that the documents are nested in an subarray, not in the top level. This code will add createdAt and updatedAt to the top level of every document. – makmonty Aug 24 '20 at 13:30
  • Could you suggest a way with mongoose? – Amanda Aug 24 '20 at 13:44
  • This is a one-time fix, why would you include it in your codebase? Anyway, it should work with mongoose as well I think, if you remove the outer curly braces – domenikk Aug 24 '20 at 13:47
  • Is there a way to auto-update the `updatedAt` field when the update happens inside `translations` ? Currently, I have to explicitly pass the `date` while updating. – Amanda Aug 25 '20 at 15:08