I am writing a program in Node.js using MongoDB and I want to update a database when certain files are modified. Inside the database I store the mtime of each database entry and I want to compare this to the mtime of the file to see if the database entry is out of date. Here is my code:
function updateArticles(articles) {
const dir = articles;
const files = fs.readdirSync(dir);
files.forEach(
(file) => {
const fpath = path.join(dir, file);
const fmtime = fs.statSync(fpath).mtimeMs;
articles.updateOne(
//refresh content and mtime if the text file has been modified
{
_id: file,
mtime: {$lte: fmtime}
},
{
$set: {content: htmlifySync(fpath), mtime: Date.now(), title: titleSync(fpath)},
//btime is only set once
$setOnInsert: {btime: Date.now()}
},
{upsert: true}
)
});
}
When I set {upsert: true}
I get a duplicate key error. When I set {upsert: false}
new entries are not added. It works if I remove the second condition in my query but then it is running htmlifySync
and titleSync
for every entry which is expensive and unneccessary.
I think the issue is that mongoDB is trying to insert a new entry which meets both query conditions which means it tries to insert a new entry with the same id. I want mtime: {$lte: fmtime}
to be a filter for the update but I don't want it to be made true by the update.
To clarify:
- If there is a DB entry for the file:
- If the file has been modified since the last DB update I want to update it
- If the file hasn't been modified since the last DB update I want to leave it unchanged
- If there isn't a DB entry for the file I want to create one