I am setting up a database trigger for insert and update. The function this will trigger will either add createdAt & updatedAt or just update the updatedAt.
ISSUE: This match expression is not filtering out the document.updates where updatedAt was the only field updated. This is causing an endless loop of triggers.
Hi, I believe there is a bit of a misunderstanding in how the match expression works (also, I am not convinced it is valid synctax with the $eq). I think this should work, but let me know if it is not what you are looking for:
Can you add to the printing to add the document’s _id to the statement (and possibly the updateDescription using EJSON.stringify()). I cant tell if something is going wrong or if there is just something inserting an object and then something updating an object
@Tyler_Kaye Does this work? I couldn’t use EJSON , I got an error “Cannot find module ‘mongodb-extended-json’”. This is the code for the function I wrote with EJSON
exports = function(changeEvent) {
const dbName = changeEvent.ns.db;
const collectionName = changeEvent.ns.coll;
const collection = context.services.get('mongodb-atlas').db(dbName).collection(collectionName);
const currentDate = new Date();
const documentId = changeEvent.documentKey._id; // Get the _id of the document
// Import the EJSON module
const EJSON = require('mongodb-extended-json');
// Check the operation type
if (changeEvent.operationType === 'insert') {
const updateDescription = {
$set: {
createdAt: currentDate,
updatedAt: currentDate
}
};
// If it's an insert, set both createdAt and updatedAt
collection.updateOne({ _id: documentId }, updateDescription)
.then(result => {
console.log(`Inserted document with _id: ${documentId} in ${collectionName} collection with createdAt and updatedAt fields. Update Description: ${EJSON.stringify(updateDescription)}`);
})
.catch(error => {
console.error('Error setting createdAt and updatedAt on insert:', error);
});
} else if (changeEvent.operationType === 'update') {
const updateDescription = {
$set: {
updatedAt: currentDate
}
};
// If it's an update, only set updatedAt
collection.updateOne({ _id: documentId }, updateDescription)
.then(result => {
console.log(`Updated document with _id: ${documentId} in ${collectionName} collection with updatedAt field. Update Description: ${EJSON.stringify(updateDescription)}`);
})
.catch(error => {
console.error('Error setting updatedAt on update:', error);
});
}
return;
};
Here is the code that actually worked
exports = function(changeEvent) {
const dbName = changeEvent.ns.db;
const collectionName = changeEvent.ns.coll;
const collection = context.services.get('mongodb-atlas').db(dbName).collection(collectionName);
const currentDate = new Date();
const documentId = changeEvent.documentKey._id; // Get the _id of the document
// Check the operation type
if (changeEvent.operationType === 'insert') {
const updateDescription = {
$set: {
createdAt: currentDate,
updatedAt: currentDate
}
};
// If it's an insert, set both createdAt and updatedAt
collection.updateOne({ _id: documentId }, updateDescription)
.then(result => {
console.log(`Inserted document with _id: ${documentId} in ${collectionName} collection with createdAt and updatedAt fields. Update Description: ${JSON.stringify(updateDescription)}`);
})
.catch(error => {
console.error('Error setting createdAt and updatedAt on insert:', error);
});
} else if (changeEvent.operationType === 'update') {
const updateDescription = {
$set: {
updatedAt: currentDate
}
};
// If it's an update, only set updatedAt
collection.updateOne({ _id: documentId }, updateDescription)
.then(result => {
console.log(`Updated document with _id: ${documentId} in ${collectionName} collection with updatedAt field. Update Description: ${JSON.stringify(updateDescription)}`);
})
.catch(error => {
console.error('Error setting updatedAt on update:', error);
});
}
return;
};
Hey, looking at your code / logs everything seems good. It seems like this is what is happening:
You are making a change to the jobs collection
This has a trigger on it autoSelectedBidAt which updates the selectedBidAt field in the document
The trigger called autoSetTimestamps responds to the initial event by updating the updatedAt field
The trigger called autoSetTimestamps responds to the change made by the other trigger (step 2) by updating the updatedAt field
Let me know if this makes sense, but I think everything is working as expected. Perhaps you were not expecting the result of one trigger to send an event for another trigger, but that is how the system works (each trigger is isolated from one another, and a trigger can even cause itself to trigger and recurse if not careful).