How to trigger a mongoose updatedAt
Asked Answered
B

3

1

I need to update my model when the data has changed. Sadly, this seems to not work.

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

const SomeSchema = new Schema({
  query: String,
  data: Object,
  userId: String,
  // Date.now() does work. I'm working with existing code.
  createdAt: { type: Date, default: moment().format() },
  updatedAt: { type: Date, default: moment().format() }
});

// Not sure why I need this 😕
// Have also used 'save' instead of 'updateOne'
SomeSchema.pre('updateOne', function(next) {
    this.updated = Date.now();
    // this.updatedAt = Date.now() does not work either.
    return next();
});

mongoose.model('someModel', SomeSchema);

Actual usage:

const mongoose = require('mongoose');
const Model = mongoose.model('someModel');

// Ideally, I wanted something like "Model.findOrCreate" but... cant see that

const obj = {..};

// Im happy nothing will error here with this.
// Would love to use "findOrCreate" instead.
const data = await Model.updateOne({ ...obj });

// I hate this so much... by hey.
if (data.n === 0) {
  // Create
  Model.create({...obj}).save
}

All Im saying is, if the data is there, update it and if not, create it. But my updatedAt key is not updating at all. It stays the same as the createdAt. Based on the docs, I dont see how I'd use $set here.

The main thing is to trigger updatedAt whenever the data was found.

Beacham answered 22/11, 2020 at 9:35 Comment(0)
S
0

Script example using MongoDB Atlas Triggers:

exports = function(changeEvent) {
  const { updateDescription, fullDocument, ns } = changeEvent;
  const updatedFields = Object.keys(updateDescription.updatedFields);
  
  // For debug
  //console.log('changeEvent', JSON.stringify(changeEvent));

  const isUpdated = updatedFields.some(field =>
    field.match(/updatedAt/)
  );
  const updatedAt = fullDocument.updatedAt;

  // Prevent update again after the update
  if (!isUpdated || !updatedAt) {
    const { _id } = fullDocument;
    
    console.log(`Triggered! ${ns.db}:${ns.coll}:${_id}, isUpdated:${isUpdated ? 'true' : 'false'}, updatedAt:${updatedAt}`);
    
    const mongodb = context.services.get(ns.db /* Cluster Name, like the DB name */);
    const collection = mongodb.db(ns.db).collection(ns.coll);
    
    collection.updateOne({
      _id: _id,
    }, {
      $set: {
        updatedAt: new Date(),
      }
    });
  }
};
Silence answered 10/8, 2022 at 18:3 Comment(0)
G
0

Looks like there is a typo in the Pre middleware function. Based on our Schema the key name is updatedAt, but in the function, it's mentioned as updated.

Griselgriselda answered 22/11, 2020 at 10:57 Comment(1)
Hi. Yes. I've also tried this.updatedAt but still the same.Beacham
S
0

Script example using MongoDB Atlas Triggers:

exports = function(changeEvent) {
  const { updateDescription, fullDocument, ns } = changeEvent;
  const updatedFields = Object.keys(updateDescription.updatedFields);
  
  // For debug
  //console.log('changeEvent', JSON.stringify(changeEvent));

  const isUpdated = updatedFields.some(field =>
    field.match(/updatedAt/)
  );
  const updatedAt = fullDocument.updatedAt;

  // Prevent update again after the update
  if (!isUpdated || !updatedAt) {
    const { _id } = fullDocument;
    
    console.log(`Triggered! ${ns.db}:${ns.coll}:${_id}, isUpdated:${isUpdated ? 'true' : 'false'}, updatedAt:${updatedAt}`);
    
    const mongodb = context.services.get(ns.db /* Cluster Name, like the DB name */);
    const collection = mongodb.db(ns.db).collection(ns.coll);
    
    collection.updateOne({
      _id: _id,
    }, {
      $set: {
        updatedAt: new Date(),
      }
    });
  }
};
Silence answered 10/8, 2022 at 18:3 Comment(0)
C
0

This line:

const isUpdated = updatedFields.some(field => field.match(/updatedAt/));

should be:

const isUpdated = updatedFields.some(field => field === "updatedAt");

because some() doesn't works with match()

Coremaker answered 1/4 at 8:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.