How to store a datetime using mongoose? - javascript

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}))

Related

Mongoose timestamp gives inacurate results

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/

Nested elements in mongoose modelling

I have to create a database in this format:
I have tried to do it like this :
var mongoose = require("mongoose")
, Schema = mongoose.Schema;
var categorySchema = new Schema({
_id: String,
subcategory: {
type: Schema.Types.ObjectId,
ref: "Subcategory"
},
id: String,
name: String,
page_description: String,
page_title: String,
parent_category: String,
c_showInMenu: Boolean
});
module.exports = mongoose.model("Category", categorySchema);
And I did the same for every subcategory, but I named them "Subcategory" and "SubsubCategory". I'm pretty much a newbie, I've read the documentation on mongoose and I've also followed an online course. I feel like I know something, but I don't understand it properly or that my logic behind it is wrong.
Also, I've managed to find this about recursive elements in Schemas, but I don't fully understand it and I don't know how to implement it to my database: Recursive elements in Schema : Mongoose modelling
I checked your code and collection image.
Here's what you are doing wrong.
You don't need to declare _id field, it's auto-generated.
Keep the column names same as they are in the given collection image.
This should be your schema declaration. Note that, this schema is for the whole collection and not just for categories array.
var mongoose = require("mongoose"),
Schema = mongoose.Schema;
var mainSchema = new Schema({
categories: [ {
id: String,
image: String,
name: String,
page_description: String,
page_title: String,
parent_category_id: String,
c_showInMenu: Boolean
}]
});
This is just an example of the schema, please add necessary changes to it.

Getting MongoDb document to expire at a certain time using mongoose [duplicate]

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.

How save data in mongodb without specific req.bodys

I discover that i don't need this:
var body = req.body;
var event = new EventModel({
dateO: dateObject,
date: body.date,
name: body.name,
type: body.type,
meetingPoint: body.meetingPoint,
info: body.info,
men: body.men,
women: body.women,
description: body.description
});
event.save.......
I can use just:
var event = new EventModel(req.body);
event.save.......
If all the inputs 'name' have the same name of my attr's in my database, mongoose can save just passing the req.body.
My question is:
I have in my HTML form the following inputs with the names:
date;
name;
type;
meetingPoint;
info;
men;
women;
description;
If i do just the var event = new EventModel(req.body), will save this values, but there is a problem:
I have this dateO, and I need to deal with it in my backend.
I tried to do the following:
req.body.dateO = what i want. But i cant use the req.body in the controller.
How can i use just the:
var event = new EventModel(req.body); and still pass the dateO??
UPDATE:
I have the following schema:
var EventSchema = new mongoose.Schema({
dateO: {
type: Date
},
date: String,
name: String,
meetingPoint: String,
info: String,
men: String,
women: String,
description: String,
});
And i have this html inputs:
<input name="date"/>
<input name="name"/>
<input name="type"/>
<input name="meetingpoint"/>
<input name="info"/>
<input name="men"/>
<input name="women"/>
<input name="description"/>
It would be perfect if it were not for one problem:
I want use the input date field in the 'DD/MM/YYYY' format, and i cant, cause mongoose just except 'MM/DD/YYYY', so i am dealing with this problems like this:
var body = req.body;
var dateObject = new Date(body['date'].replace( /(\d{2})\/(\d{2})\/(\d{4})/, "$2/$1/$3"));
Them i can send like the way that i want to my database. My question is:
How can i send the dataO using the new event model in just one line:
var event = new EventModel(req.body);
You should be using a Date object here directly and not setting other field. It would be much more simple for your client code to just use a timestamp value in the form, which can even be obtained from it's own Date object handler.
That' the clean good advice, but you just need some extra smarts in your schema to obtain a date object from the "string" in the Date field:
var EventSchema = new mongoose.Schema({
dateO: {
type: Date
},
date: String,
name: String,
meetingPoint: String,
info: String,
men: String,
women: String,
description: String,
});
eventSchema.pre('save',function(next) {
this.dateO =
new Date(this.date.replace( /(\d{2})\/(\d{2})\/(\d{4})/, "$2/$1/$3"));
next();
});
So just move your logic into a "pre save" hook, and the field will be created based on the current data before the .save() is processed.

Automatic createdAt and updatedAt fields in Meteor

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()

Categories