Is there a way to convert a date value to a User's timezone in Mongoose? - mongodb

I have searched everywhere, StackOverflow and else where but I can't seem to find a fix for my problem. I have a mongoose schema like this:
// user.model.js
const mongoose = require('mongoose');
const User = new Schema({
firstName: String,
lastName: String,
tz: String,
registrationDate: {
type: Date,
default: Date.now(),
}
})
And I have a controller which creates a User like this:
// user.controller.js (async)
let user = await User.create({
'firstName': 'John',
'lastName': 'Doe',
'tz': 'Africa/Kampala'
});
await reply.send(user); // I am using Fastify framework
No matter what I do, when the User is returned it always gives the UTC time and not the time that the User actually is in. have tried using Mongoose transform:
// Transform on the schema
const moment = require('moment-timezone');
const User = new Schema({
// Schema definitions
}, {
toJSON: {
transform: function (doc, ret) {
ret.registrationDate= moment.tz(doc.registrationDate, doc.tz).format();
return ret;
}
}
})
And have also tried using get like this:
const User = new Schema({
// Other definitions
registrationDate: {
type: Date,
default: Date.now(),
get: convertDate
}
})
function convertDate(registrationDate) {
return moment.tz(registrationDate, this.tz).format()
}
But no luck. I would appreciate any assistance or guidance in getting this to work on the model. Thanks!

Related

Mongoose distinct returns empty array

I have the following schema and query. I'm trying to retrieve all tags in my document by using the .distinct() method but that's not working. Any suggestions would be great.
const postingSchema = new mongoose.Schema({
time: String,
date: String,
company: String,
position: String,
description: String,
tags: Array,
});
router.get('/tags', async function(req, res){
const tags = await Postings.find({}).distinct("tags").exec();
if(!tags){
return res.status(404).json({message: "No Tags!"});
}
return res.status(200).json(tags);
}

How to trigger a mongoose updatedAt

I need to update my model when the data has changed. Sadly, this seems to not work.
const mongoose = require('mongoose');
const moment = require('moment');
const Schema = mongoose.Schema;
const SomeSchema = new Schema({
query: String,
data: Object,
userId: String,
// Date.now() does work. I'm working with existing code.
createdAt: { type: Date, default: moment().format() },
updatedAt: { type: Date, default: moment().format() }
});
// Not sure why I need this 😕
// Have also used 'save' instead of 'updateOne'
SomeSchema.pre('updateOne', function(next) {
this.updated = Date.now();
// this.updatedAt = Date.now() does not work either.
return next();
});
mongoose.model('someModel', SomeSchema);
Actual usage:
const mongoose = require('mongoose');
const Model = mongoose.model('someModel');
// Ideally, I wanted something like "Model.findOrCreate" but... cant see that
const obj = {..};
// Im happy nothing will error here with this.
// Would love to use "findOrCreate" instead.
const data = await Model.updateOne({ ...obj });
// I hate this so much... by hey.
if (data.n === 0) {
// Create
Model.create({...obj}).save
}
All Im saying is, if the data is there, update it and if not, create it. But my updatedAt key is not updating at all. It stays the same as the createdAt. Based on the docs, I dont see how I'd use $set here.
The main thing is to trigger updatedAt whenever the data was found.
Script example using MongoDB Atlas Triggers:
exports = function(changeEvent) {
const { updateDescription, fullDocument, ns } = changeEvent;
const updatedFields = Object.keys(updateDescription.updatedFields);
// For debug
//console.log('changeEvent', JSON.stringify(changeEvent));
const isUpdated = updatedFields.some(field =>
field.match(/updatedAt/)
);
const updatedAt = fullDocument.updatedAt;
// Prevent update again after the update
if (!isUpdated || !updatedAt) {
const { _id } = fullDocument;
console.log(`Triggered! ${ns.db}:${ns.coll}:${_id}, isUpdated:${isUpdated ? 'true' : 'false'}, updatedAt:${updatedAt}`);
const mongodb = context.services.get(ns.db /* Cluster Name, like the DB name */);
const collection = mongodb.db(ns.db).collection(ns.coll);
collection.updateOne({
_id: _id,
}, {
$set: {
updatedAt: new Date(),
}
});
}
};
Looks like there is a typo in the Pre middleware function. Based on our Schema the key name is updatedAt, but in the function, it's mentioned as updated.

Google Calendar API (Saving events in MongoDB, Express JS)

I can't figure out how to save fetched events from Calendar API. I was able to print out array of events in console. I would require save multiple events at once and have verification if they already exist in database with unique id.
Here's my event.js scheme in express js.
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const EventSchema = new Schema({
id: {
type: String,
required: false,
unique:true
},
start: {
type: String
},
end: {
type: String
},
status: {
type: String
},
creator: {
type: Array
},
description: {
type: String
}
});
module.exports = Event = mongoose.model('events', EventSchema);
Here's my event.js router in express js.
router.post("/google/get", async (req, res, next) => {
const {
google
} = require('googleapis')
const {
addWeeks
} = require('date-fns')
const {
OAuth2
} = google.auth
const oAuth2Client = new OAuth2(
process.env.GOOGLE_CLIENT_ID,
process.env.GOOGLE_CLIENT_SECRET
)
oAuth2Client.setCredentials({
refresh_token: process.env.GOOGLE_REFRESH_TOKEN,
})
const calendar = google.calendar({
version: 'v3',
auth: oAuth2Client
})
calendar.events.list({
calendarId: 'MY CALENDAR ID',
timeMin: new Date().toISOString(),
timeMax: addWeeks(new Date(), 1).toISOString(),
singleEvents: true,
orderBy: 'startTime',
},
function (err, response) {
if (err) {
console.log("The API returned an error: " + err)
return
}
var events = response.data.items
events.forEach(function (event) {
var start = event.start.dateTime || event.start.date
console.log("%s - %s", start, event.summary)
})
}
)
In Mongoose, in order to save something to a database, all you need to do is to instantiate the model that you created. Your event schema exports Event as a model that you can then treat as a regular object. So you would do something along the lines of:
let currentEvent = new Event({id, start, end, status, creator, description});
currentEvent.save();
Once that is done, it should be stored in your MongoDB. I assume that as the code for this is not visible it is already set up and working. You can just run the above inside of your for loop with some minor tweaks to grab each value correctly and it should sort your issue out!
As for your unique ID and making sure that it doesn't already exist in your database, you can use the same model to find values by checking the id against your database and seeing if it exists. As follows:
Event.findById(id, (err, event) => {
if(event == null) {
let currentEvent = new Event({id, start, end, status, creator, description});
currentEvent.save();
} else {
alert("Error, this event already exists")
}
});
I believe something like this should work, however I might have it wrong with how to check if the event exists, I can't remember if it returns null or something different, so just console log the value of event and check to see what it returns if there isn't an event that exists with that ID, and just re-run your if statement with that instead.

mongoose not fetching data

I am trying to fetch all users from a MongoDB database. However for some reason recently the request did not fetch anything.
Here is the code in which I try to fetch the data:
app.get('/api/allusers', (req, res) => {
Employee.find()
.then(rettrievedData => {
res.json(rettrievedData)
});
});
Here is the mongoose model:
const mongoose = require('mongoose');
const employeeSchema = mongoose.Schema({
name: { type: String },
surName: { type: String },
mail: { type: String },
phone: { type: String },
});
module.exports = mongoose.model('Employee', employeeSchema, 'employee.employees');
Here is the code for connecting to Mongo
mongoose.connect("mongodb+srv://Kiril:xxxxxxxxxxxxx#cluster0-owdfy.mongodb.net/employee?retryWrites=true&w=majority")
.then(() => {
console.log("Connected")
})
Also I have checked that there is data in the database, but for some reason the Employee.find() does not retrieve anything. What can be reason?
Thanks in advance.
why you are adding 'employee.employyes' when you creating your model
try to export the model without it
module.exports = mongoose.model('Employee', employeeSchema)
or better
exports.Employee = mongoose.model('Employee', employeeSchema)
and require it where you want to use it
const Employee = require('path to the schema file')

Unable to query sub document mongoose

I've schema like this and i', trying to get the document from the array using _id. This is my first Mongo project that I'm working, please help me how can I achieve the. I basically want to retrieve the sub document corresponds to the id and update some data in that.
var PhoneSchema = new mongoose.Schema({
type: String,
number: String
});
var StudentSchema = new mongoose.Schema({
name: String,
dept: String,
phone: [PhoneSchema]
});
var Phone = mongoose.model('Phone',PhoneSchema);
var Student = mongoose.model('Student',StudentSchema);
I've tried the following ways, but none of them are working.
Method 1: When I tried the same in the console it is giving me the parent document along with the sub document that corresponds to the phoneId
Student.findOne({"phone._id":new mongoose.Schema.Types.ObjectId(phoneId) }, {'phone.$':1}, function(err, student) {
}
Method 2: As per the mongoose documentation to retrieve sub documents, in this case I'm getting exception saying phone is undefined
Student.phone.Id(phoneId);
I've fixed this by removing Schema from the below query
Student.findOne({"phone._id":new mongoose.Types.ObjectId(phoneId) }, {'phone.$':1}, function(err, student) {
}
i tried to solve your requirement. The following code did the job.
var PhoneSchema = new mongoose.Schema({
type: String,
number: String
});
var StudentSchema = new mongoose.Schema({
name: String,
dept: String,
phone: [PhoneSchema]
});
var Phone = mongoose.model('Phone',PhoneSchema);
var Student = mongoose.model('Student',StudentSchema);
var newPhone = new Phone({
type: 'ios', number: '9030204942'
});
var newStudent = new Student({
name:'Pankaj',
dept:'cse',
phone:newPhone
});
// newStudent.save(function(err, ph) {
// if (err) return console.error(err);
// });
Student.findOne({"phone._id":mongoose.Types.ObjectId('587e6409e06170ba1708dc21') },{_id:0,phone:1}, function(err, phone) {
if(err){
console.log(err)
}
console.log(phone);
});
Find the following screenshot with result