I have a Node/Express API that sets a timestamp on a Mongoose model:
var NotificationSchema = new Schema({
created_on: {
type: Number,
default: new Date().getTime()
},
. . .
});
When I convert this into a Python datetime in Django:
created_on = datetime.fromtimestamp(notification['created_on'] / 1000.0)
it's exactly 3 minutes behind. Both applications are running on the same server. What's going on with this timestamp?
Got this figured out. It was as simple as specifying the default value as:
var NotificationSchema = new Schema({
created_on: {
type: Number,
default: Date.now
},
. . .
});
Now each time a model gets saved, Date.now is called properly.
Related
CreatedAt gives the time 3 hours ago. How can i make it display the current time?
The schema:
import mongoose from 'mongoose';
var articleSchema = new mongoose.Schema({
title: String,
text: String,
link: String,
description: String,
imgLink: String,
source: String,
} , { timestamps: true }
);
articleSchema.index({ createdAt: 1, expires: '60m', default: Date.now });
var Article = mongoose.model("Article", articleSchema);
export default Article;
You probably getting different time zone from mongoose.
Try installing npm i moment-timezone
And change your Date to the right timezone, here is the docs for that: https://momentjs.com/timezone/docs/#/using-timezones/parsing-in-zone/
I made this to store data of some meetings but I want the field "date" to store values as datetime like in a mysql base. How can I do this?
const mongoose= require('mongoose')
const Schema= mongoose.Schema
const Meets= mongoose.model('Meet', new Schema({
id1: String,
id2: String,
date: Date
}))
module.exports= Users
Your schema should be in below format for store Meeting time in DateTime format.
const mongoose= require('mongoose')
const Schema= mongoose.Schema
const Meets= mongoose.model('Meet', new Schema({
// First meeting recipient
id1: { type: Schema.Types.ObjectId, required: true },
// Second meeting recipient
id2: { type: Schema.Types.ObjectId, required: true },
// Date and Time of meeting
date: { type: Date, required: true }
}))
module.exports= Meets
Now, When you will make an entry in Meets collection, You will find below format of date key in your mongo database:
ISODate("2017-04-02T15:30:00Z")
This represents that the above is in ISO Date format which gives time into UTC format. To convert it in your local time format, you can do below step:
new Date(meet.date).toLocaleString();
Also, you can set property {timestamps:true} in your schema, which will additionally add createdAt and updatedAt field in your collection, which will automatically get updated at creation and each update.
Thanks
What kind of date format you want to store? If you want it to be stored in milliseconds, then you can set timestamps option to true like this:
const Meets= mongoose.model('Meet', new Schema({
id1: {String},
id2: {String},
}, {timestamps:true}))
I am working on a database system using MongoDB. I am trying to save the current date and time, then update it if the same barcode on ID cards is scanned twice, thrice, etc... However, the $set will not update the item. I have already looked at MongoDB documentation and other Stack Overflow posts, but nothing seems to work. Other Stack Overflow posts suggested adding
{ new: true }
and
( overwrite: true }
I tried these both separately and in tandem neither worked.
My Code:
Student.findOne({StudNum: studNum}, function(err, studNumItem) {
if (err) {
res.send("MongoDB Error: " + err);
return false;
}
if (!studNumItem) {
var myData = new Student({ StudNum: studNum, Attendance : 1, LastDateTimeAttended : {
Year: year, Month: month, Day: day, Hours: hours, Min: min, Sec: sec
}});
myData.save()
.then(item => {
res.send("saved to database: " + studNum + ", with attendance " + Attendance + "");
})
.catch(err => {
res.send("unable to save to database: " + studNum + ", for attendance " + Attendance + "");
});
}
else{
var conditions = {StudNum: studNum};
var update = {$inc : { Attendance: 1 }, $set : {
"Year": year, "Month": month, "Day": day, "Hours": hours, "Min": min, "Sec": sec
}};
Student.findOneAndUpdate(conditions, update, { new: true }, function (err)
{
if (err) // If error
{
res.send(err);
}
else {
res.send("Checked in!")
}
});
}
});
And my Schema:
var studentSchema = mongoose.Schema({
StudNum: String,
Attendance: Number,
LastDateTimeAttended: {
Year: Number,
Month: Number,
Day: Number,
Hours: Number,
Min: Number,
Sec: Number
}
});
Thanks in advance!
Edit: Just to clarify, saving the item works fine, but updating the item does not, also no errors are thrown while updating.
In your case, I'm not sure it is your find one and update that is the issue. I believe since what you are trying to update is a nested object, you need to prepend it with the top level property to get mongoose to save it. Since those properties don't exist at a top level, mongoose is just throwing it away.
var update = {
$inc : {
Attendance: 1
},
$set : {
"LastDateTimeAttended.Year": year,
"LastDateTimeAttended.Month": month,
"LastDateTimeAttended.Day": day,
"LastDateTimeAttended.Hours": hours,
"LastDateTimeAttended.Min": min,
"LastDateTimeAttended.Sec": sec
}
};
For those who don`t know the cause of the issue, it also may be that the variable is not declared in the scheme causing any alteration to be halted and ignored.
I suggest you try saving you date as a string.
LastDateTimeAttended in your model should expect a string, and new Student constructor should create LastDateTimeAttended variable by calling
let date = new Date();
LastDateTimeAttended = date.toString();
your new schema should look like
var studentSchema = mongoose.Schema({
StudNum: {type: String, required: true},
Attendance: {type: Number, required: true},
LastDateTimeAttended: {type: String, required: true}
});
you should then be able to update your mongodb document
Student.findOneandUpdate(conditions, update, callback). see working with mongoose Model.findOneandUpdate
Below is the command that can be used via the mongo terminal to set an expiry time for collections (a TTL):
db.log.events.ensureIndex( { "status": 1 }, { expireAfterSeconds: 3600 } )
How do I do this from my code in Node.js using mongoose?
In Mongoose, you create a TTL index on a Date field via the expires property in the schema definition of that field:
// expire docs 3600 seconds after createdAt
new Schema({ createdAt: { type: Date, expires: 3600 }});
Note that:
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.
{ createdAt: { type: Date, expires: 3600, default: Date.now }}
this code is working for me.
may it help
let currentSchema = mongoose.Schema({
id: String,
name: String,
packageId: Number,
age: Number
}, {timestamps: true});
currentSchema.index({createdAt: 1},{expireAfterSeconds: 3600});
Providing a string to expires also works nicely with Mongoose if you do not want to deal with the expire time calculation and improve the overall readability of the schema.
For example here we are setting the expires to 2m (2 minutes) and mongoose would convert to 120 seconds for us:
var TestSchema = new mongoose.Schema({
name: String,
createdAt: { type: Date, expires: '2m', default: Date.now }
});
Mongoose would create an index in the background and auto set the expireAfterSeconds to in this case 120 seconds (specified by the 2m).
It is important to note that the TTL process runs once every 60 seconds so it is not perfectly on time always.
If you are working with Mongodb Atlas Replica Sets - try:
import * as mongoose from 'mongoose';
let currentSchema = new mongoose.Schema({
createdAt: { type: Date, expires: 10000, default: Date.now },
id: String,
name: String,
packageId: Number,
age: Number
});
currentSchema.index({"lastModifiedDate": 1 },{ expireAfterSeconds: 10000 });
new Scehma({
expireAt: {
type: Date,
expires: 11,
default: Date.now
}
)}
This is the solution that worked for me according to this in the current Mongoose docs.
There is a npm library - 'mongoose-ttl'.:
var schema = new Schema({..});
schema.plugin(ttl, { ttl: 5000 });
you can see all the options of this library:
https://www.npmjs.com/package/mongoose-ttl
const Schema = new mongoose.Schema({id: {
type: Number},
createdAt: {
type: Date, expires: '4h', index: true,
default: Date.now}});
You need to add index: true while creating you schema
9/2022 Working Solution using Mongoose 6.5.4
None of the answers here worked for me, but I was able to finally get it working using the latest version of Mongoose currently available, 6.5.4.
Say our Schema looks like this:
const MySchema = new mongoose.Schema({
id: { type: Number },
myCustomTTLField: { type: Date }
});
myCustomTTLField is the field you want to index and have control the expiration. To achieve this, we add the following under our schema definition:
MySchema.path('myCustomTTLField').index({ expires: 60 });
The argument in MySchema.path is the name of the field you want to index for TTL. The expires option should be the number of seconds that will elapse from the Date represented in myCustomTTLField before the document is deleted. In the example above, the document will be deleted 60 seconds after whatever date is saved in myCustomTTLField. The full example:
const MySchema = new mongoose.Schema({
id: { type: Number },
myCustomTTLField: { type: Date }
});
MySchema.path('myCustomTTLField').index({ expires: 60 });
Please let me know if this works for you, I hope this helps. Mongoose TTL has been a thorn in my side for a long time, as their docs are notoriously tough to navigate. I found this solution via a small example buried in the docs here.
IMPORTANT NOTE:
TTL is not guaranteed to happen at exactly the time specified by your date + expiration seconds. This is due to how MongoDB's background delete process works. It runs every 60 seconds, so you may theoretically wait up to 60 seconds past expected TTL before seeing your document deleted. More info on that from the MongoDB docs.
FWIW I could only get the expires feature to work on a field called expiresAt. Here's my interface, and schema for implementing this in Typescript.
import { model, Schema, Types } from 'mongoose';
export interface ISession {
sessionId: string;
userId: Types.ObjectId;
role: string;
expiresAt?: Date;
}
const sessionSchema = new Schema<ISession>({
sessionId: { type: String, required: true, indexes: { unique: true} },
userId: { type: Schema.Types.ObjectId, required: true, ref: 'users'},
role: { type: String, required: true, enum: [ 'ADMIN', 'BASIC_USER' ]},
expiresAt: { type: Date, expires: '1h', default: Date.now }
}, { versionKey: false });
Reading the Mongoose documentation it seems like all the other proposed solutions should work too. I don't know why they were not for me. You can read the official Mongoose docs on expiresAt here.
In my collection I'd like to have automatically generated createdAt and updatedAt fields that would contain the date of when the object was inserted / updated for the last time - kind of like it's happening in Ruby on Rails. Currently I'm doing this with an observer similar to this one:
MyCollection.find({}).observeChanges({
changed: function(id, changes) {
MyCollection.update(id, ...);
},
});
Is there a better / more efficient / more straightforward way?
I use Collection2. It supports autoValue in the schema, a function that computes the forced value of a field. As these two fields are used in all collections, you can save them to a variable:
#SchemaHelpers =
createdAt:
type: Date
autoValue: ->
if #isInsert
return new Date
if #isUpsert
return $setOnInsert: new Date
if #isUpdate
#unset()
return
updatedAt:
type: Date
autoValue: ->
return new Date
And then in the collection:
Schema = {}
Posts = new Meteor.Collection("posts")
Schema.Posts = new SimpleSchema
createdAt: SchemaHelpers.createdAt
updatedAt: SchemaHelpers.updatedAt
title:
type: String
max: 30
body:
type: String
max: 3000
Posts.attachSchema(Schema.Posts)
This solution makes updatedAt always present and its value will be very close to createdAt when it is just inserted (not necessarily the same). If you need updatedAt not to be set when inserting, you can use something like the example in the Collection2 readme:
updatedAt: {
type: Date,
autoValue: function() {
if (this.isUpdate) {
return new Date();
}
},
denyInsert: true,
optional: true
},
but this does not handle upserts. I don't know any good solution that handles upserts correctly and leaves the field empty at inserts.
I like https://github.com/matb33/meteor-collection-hooks
collection.before.insert (userId, doc) ->
doc.createdAt = new Date().valueOf #toISOString()