How do I reset the expiration date of a document in Mongoose? - node.js

Based on the answer in this post I have created the following document schema, which sets every new document created to expire 24 hours after its creation :
var mongoose = require('./node_modules/mongoose');
mongoose.connect(mongodburi, {
server : {
socketOptions : {
keepAlive: 1
}
},
replset : {
socketOptions : {
keepAlive: 1
}
}
});
var sessionSchema = mongoose.Schema({
uid: {
type: String,
required: true,
unique: true
},
token: {
type: String,
required: false,
unique: true
},
createdAt: {
type: Date,
default: Date.now,
expires: 24*60*60
}
});
var Session = mongoose.model('Session', sessionSchema);
I want to be able to reset the expiration of a document for another 24 hours. Is this the way to do it (?) :
Session.update({uid: someUID}, {createdAt: Date.now}, null, function (err, numOfSessionsUpdated)
{
if (numOfSessionsUpdated > 0)
{
console.log('session expiration has been postponed for another 24 hours');
}
});

That's close, but you need to call Date.now instead of just passing it as that's a function:
Session.update({uid: someUID}, {createdAt: Date.now()}, null, function (err, numOfSessionsUpdated)
{
if (numOfSessionsUpdated > 0)
{
console.log('session expiration has been postponed for another 24 hours');
}
});

Related

MongoDB TTL index document not deleted on time

I am trying to delete a MongoDB document after 5 minutes but it deleted almost after 2 min. I exactly don't know the issue. Any help is highly appreciated.
const hospitalRecordSchema = new mongoose.Schema({
hospital_id: {
type: String,
},
hospital_name: {
type: String,
},
created_at: {
type: Date,
default: new Date(),
expires: "5m",
index: true,
},
data: {
type: Object,
default: {},
},
});
hospitalRecordSchema.index({ created_at: 1 }, { expireAfterSeconds: 300 });
module.exports = mongoose.model("HospitalRecord", hospitalRecordSchema);

Mongoose - Set TTL on MongoDB Document

I am trying to set a TTL via mongoose when a document is created in MongoDB, but I'm not having any luck with any of my attempts. Latest version of mongoose is being used in my project and from what I can tell I've tried the most common answers here on SO and elsewhere online.
My Schema
const mongoose = require('mongoose');
const jobSchema = new mongoose.Schema(
{
positionTitle: {
type: String,
},
description: {
type: String,
}
});
const Jobs = mongoose.model('job', jobSchema);
module.exports = Jobs;
I have tried adding a createdAt with expires based on this question answer:
const jobSchema = new mongoose.Schema({
positionTitle: {
type: String,
},
description: {
type: String,
},
createdAt: { type: Date, expires: 3600 },
});
Along with this option that's also in the same question to have createdAt be created automatically via timestamps:
const jobSchema = new mongoose.Schema(
{
positionTitle: {
type: String,
},
description: {
type: String,
},
},
{ timestamps: true }
);
Trying variations of the following to set an index with timestamps defined:
jobSchema.index({ createdAt: 1 }, { expires: 86400 });
jobSchema.index({ createdAt: 1 }, { expires: '1 day' });
jobSchema.index({ createdAt: 1 }, { expireAfterSeconds: 3600 });
Regardless of which option I try, the document is removed after MongoDB's 60-second cycle when a createdAt field is set on the document. Would really love to know what I'm doing wrong.
After trying all the solutions in the thread you mentioned, none of them worked. In the end this code did the trick. It involves setting the expireAt field to the actual time that you want it deleted, which makes sense really.
const Schema = mongoose.Schema;
const YourSchema = new Schema({
expireAt: {
type: Date,
default: Date.now() + 10 * 60 * 1000 // expires in 10 minutes
},
});
This is the only thing that worked, all the other solutions I tried always deleted after 1min, no matter the amount of time I added.
I've been having issues with this as well. I found this thread here https://github.com/Automattic/mongoose/issues/2459 and it worked for me. Translated into your code would look like this.
const mongoose = require('mongoose');
const jobSchema = new mongoose.Schema(
{
positionTitle: {
type: String,
},
description: {
type: String,
},
expireAt: {
type: Date,
default: Date.now,
index: { expires: '5s' }
}
});
const Jobs = mongoose.model('job', jobSchema);
module.exports = Jobs;
On the link I added, it is the very last solution. I'm not exactly sure what this is doing but here is the mongo link of what it should be doing for anyone else with this issue. https://docs.mongodb.com/manual/tutorial/expire-data/. To change the amount of time that you need the document just change the expires. It accepts '#s' and '#d' for sure. Also if you want your document to be deleted at a specific time then you can do this.
expireAt: {
type: Date,
default: new Date('July 22, 2013 14:00:00'),
index: { expires: '0s' }
}
This will delete the document 0 seconds after the specified date.
Problem in TTL, Reason behind Document does not delete after some / few seconds, how to expire document in MongoDB / Mongoose using schema. Solution expireAfterSeconds / expires / index.
NOTE: - MongoDB's data expiration task runs once a minute, so an expired doc might persist up to a minute past its expiration. This feature requires MongoDB 2.2 or later. It's up to you to set createdAt to the current time when creating docs or add a default to do it for you as suggested here.
NOTE :- Below code is working fine and the document will delete after 5 minutes.
const verficationSchema = new mongoose.Schema({
email: {
type: String,
required: true,
unique: true,
lowercase: true,
trim: true,
validate(email) {
if (!validator.isEmail(email)) {
throw new Error("Email is not valid!");
}
},
},
otp: {
type: Number,
required : true
},
expireAt : {
type: Date,
default: Date,
expires : 300 // means 300 seconds = 5 minutes
}
});
NOTE :- Upper code is working fine, But document will delete after 1 minutes, because MongoDB check expiration procedure after every 1 minutes.
const verficationSchema = new mongoose.Schema({
email: {
type: String,
required: true,
unique: true,
lowercase: true,
trim: true,
validate(email) {
if (!validator.isEmail(email)) {
throw new Error("Email is not valid!");
}
},
},
otp: {
type: Number,
required : true
},
expireAt : {
type: Date,
default: Date,
expires : 8 // means 8 seconds
}
});

Mongoose unique value per day

Im trying to configure mongoose schema unique param. I need to allow write to DB no more than one unique author per one day period.
Schema.index( { author: 1, created: 1 } , { unique: true} ) not works, here I can't enter time period.
What better way to decide this case?
const Report = new Schema({
author: {
type: mongoose.Schema.Types.ObjectId,
ref: 'DiscordUserList',
required: true
},
reports: [{ reportNum: { type: Number }, text: { type: String }, date: { type: Date, default: Date.now } }],
questionsDone: [{ questionNum: { type: Number }, done: { type: Boolean }, date: { type: Date, default: Date.now } }],
created: {
type: Date,
default: Date.now
}
}, { strict: false })
Report.plugin(mongoosePaginate)
const reportListSchema = mongoose.model('ReportList', Report)
module.exports = reportListSchema
You could do an update operation with $setOnInsert and upsert option i.e if the update() with upsert: true had found a matching document, then MongoDB performs an update, applying the $set operation but ignoring the $setOnInsert operation. Thus your typical update would be as follows:
import moment from 'moment'
const start = moment().startOf('day').toDate() // set to 12:00 am today
const end = moment().endOf('day').toDate() // set to 23:59 pm today
ReportList.findOneAndUpdate(
{
'author': author_id,
'created': { '$gte': start, '$lte': end }
},
{
'$set': { 'author': author_id },
'$setOnInsert': { 'created': moment().toDate() }
},
{ 'upsert': true, 'new': true },
(err, report) => {
console.log(report)
}
)
or using the setDefaultsOnInsert option which when this and upsert are true, mongoose will apply the defaults specified in the model's schema if a new document is created:
ReportList.findOneAndUpdate(
{
'author': author_id,
'created': { '$gte': start, '$lte': end }
},
{ '$set': { 'author': author_id } },
{
'upsert': true,
'new': true,
'setDefaultsOnInsert': true
},
(err, report) => {
console.log(report)
}
)

Why expires is not working in mongoose model?

So this is my model and I want to do that when it's created in DB to remove it from there after one hour. But this not working. I got no errors also. It expires after few seconds.
var mongoose = require('mongoose');
var Revive = mongoose.model('Revive', {
username: {
type: String,
required: true
},
count: {
type: Number,
default: 0,
max: 4
},
expire_at : { type : Date, index : { expires : '60m' }, default: Date.now }
});
module.exports = {Revive};

How do I access `findAndModify` method from Mongo in Node (with Mongoose)?

This is /models/joke.js:
var mongoose = require ('mongoose')
, database = mongoose.connect('localhost', 'joke', { server: { poolSize: 3 } });
var jokeSchema = mongoose.Schema({
content: String,
upvotes: {
type: Number,
default: 0
},
downvotes: {
type: Number,
default: 0
},
views: {
type: Number,
default: 0
},
published: {
type: Boolean,
default: true
},
author_id: Number,
created: {
type: Date,
default: Date.now
}
});
var Joke = mongoose.model('Joke', jokeSchema);
module.exports = Joke;
And I'm doing this to check if something exist — if doesn't, then create:
var Joke = require ('./models/joke');
// ...
Joke.findAndModify({
query: {
content: content
},
update: {
$setOnInsert: {
content: "test",
}
},
new: true,
upsert: true
});
But my console shout me the following:
TypeError: Object function model(doc, fields, skipId) {
if (!(this instanceof model))
return new model(doc, fields, skipId);
Model.call(this, doc, fields, skipId);
} has no method 'findAndModify'
I can understand the reason for the error – I'm calling it through a model instead of a collection, but how do I access my Jokes' collection methods?
I mean, all of the examples were using db.collection.findAndModify, but what is this db.collection? How do I call it?
To access findAndModify update functionality from Mongoose, use findOneAndUpdate:
Joke.findOneAndUpdate(
{ content: content },
{ $setOnInsert: { content: "test" } },
{ new: true, upsert: true },
callback
);

Resources