How to updateMultiple documents in mongoose base on current value of document - node.js

I have the following mongodb model:
const schema = new Schema({
timezone: {
type: String,
},
datetimeBaseOnTimezone: {
type: Date,
}
})
I want to update the datetimeBaseOnTimezone with the current Date for each document in database based on the current timezone of each document this using a single query.
Something like this:
await Model.updateMany({},(element) => ({
datetimeBaseOnTimezone: new Date(new Date().toLocaleString('en-US', { timeZone: element.timezone }))
}));
Is there any solution similar to this approach?

Starting with a few assumptions:
the datetimeBaseOnTimezone string has the same format for all documents
the timezone string contains an Olson timezone identifier or a UTC offset
you are using MongoDB 4.2 or newer
You could use the pipeline form of update, along with the $dateFromString operator, which might look something like:
Model.updateMany({},[{$set:{datetimeBaseOnTimezone:{$dateFromString:{
dateString:"$datetimeBaseOnTimezone",
format: <see dateFromString docs>,
timezone: "$timezone",
onError: "$datetimeBaseOnTimezone",
onNull: "$datetimeBaseOnTimezone"
}}}])

Related

Store wrong timezone in default date and time

I am trying to store default date and time using mongoose with the Node.JS but somehow, it is storing different time zone value in database. I'm using "MongoDB Atlas Database" as a DB server and also configured default time zone with reference to this. I have also tried this for change time zone and also tried "moment-timezone.js", But didn't get any luck.
I just want to store default date and time with Indian standard time format.
Following is my code for the schema.
const testSchema = new mongoose.Schema({
from: String,
to: String,
amount: Number,
message: {
type: String,
default: ""
},
creationdate: {
type: Date,
default: Date.now
}
});
Please help me with this issue. Show me the best way to solve this problem.
MongoDB stores Date fields as a UTC timestamp in milliseconds since the Unix epoch, which is a 64bit integer (53bit in JS). This is also what Date.now() is. There is no timezone component to the data by design.
If you need a consistent timezone format for a Date object, add a virtual field that returns the required timezone adjusted string or object from the date.
const testSchema = new mongoose.Schema({
creationdate: {
type: Date,
default: Date.now
}
});
testSchema.virtual('formattedCreationDate').get(function() {
return this.creationdate.toLocaleString(); // or day.js/luxon
});
If you need a timezone other than the user or system supplied value, store the required TZ data in another field and use that timezone field in the virtual formatting.
The virtual will probably be easier if you use day.js or luxon.

Nodejs Cannot find document when using .find({}) method

I am trying to do a simple .find() using mongoose/nodejs with mongoDB. I have a document (with field "date": "09-20-2019") in my collection (show) but I cannot seem to find it programmatically.
I have tried using MongoDB compass (db viewer software) to perform a search for what I am looking for. I passed into the search box under my collection {date: "09-20-2019"} and I was able to find the document using their search functionality so I know it should be working. I have checked that the field "date" is coming across to back end node server as the correct format and value of "09-20-2019". I am using Node.js 10.15.1
--This is from my route.js file
router.get('/shows/:date', (req, res, next)=>{
//res.send('Retrieving the shows list');
console.log('back end date: ' + req.params.date);
Show.find({date: req.params.date}, function(err, result){
if (err)
{
res.json(err);
}
else {
console.log(result);
res.json(result);
}
})
});
--This is from my show.js (mongodb schema file)
const mongoose = require('mongoose');
const ShowSchema = mongoose.Schema({
name:{
type: String,
required: true
},
date:{
type: String,
required: true
},
venue:{
type: String,
required: true
},
createdDate:{
type: String,
required: true
}
});
const Show = module.exports = mongoose.model('Show', ShowSchema);
--This is from my service.ts file
getShow(date)
{
var headers = new Headers();
headers.append('Content-Type', 'application/json');
//date is in format MM/dd/yyyy (e.g. 09-20-2019)
return this.http.get<Show>('http://localhost:3000/api/shows/' + date);
}
--This is from my component
this.commentCardService.getShow(this._date).subscribe(data => {
console.log(data);
});
I am expecting the .find({}) operation to return with a single document from my mongoDB of the show with the date of '09-20-2019' which is the only document that is in that collection at the moment. More than one document will exist in the collection ultimately.
Please see also: https://stackoverflow.com/a/55386123/211827 — when querying dates, use actual dates. When querying ObjectIds use real ObjectIds. Etc. Because your strings are literally the worst possible date format for any form of lexicographical expectation. Specifically: not following the ISO date format form of least specific to most specific (year, month, day) will prevent any form of sorting, range querying, or essentially any of the "most useful" things you can use actual dates for when stored as strings, which is not an appropriate storage format for dates, generally.
"2019/09/21" = 11 bytes. The same date represented using the Julian calendar: 2458748, or a 32-bit integer (4 bytes), no time component. UNIX timestamp would be 64-bit, so 8 bytes, and you'd also have to throw away or ignore the time component within. Even the wrong right way is better than the wrong wrong way. ;)
Check-in you Database that there is date formate like '02/03/1995', it can be via saving, you are changing you formate if not then please share your one object of your schema.
This is working properly in my schema.
db.getCollection('users').find({dob:'02/03/1995'})
Check whether your date in db is in iso date or iso string format.
If it is an iso date than you will have to do new Date(09-20-2019).
If its an iso string then you also need to consider the timezone.
Try to find using a between query 09-20-2019 & 09-21-2019.
You should get the data.

Using MomentJS for Default Date in MongoDB Document

I'm trying to use MomentJS to get non-localized UTC time and set that as the default for new documents created in Mongo.
var SubFavoriteSchema = new Schema({
user : { type: String, ref: 'Account'},
date : {type: Date, default: moment.utc()}
});
The problem is, moment.utc() returns the date that the Node server started. Thus if I start the server on Jan 1, all the documents get a UTC time of Jan 1, even if the document is created on Jan 10.
Any idea why it keeps getting the server's start time instead of the current time?
The problem is that you're calling the moment.utc() function (once) when creating the schema, so the same resulting value is used when creating new documents.
However, you don't need to use moment for this, default: Date.now will do what you want as that function returns the current UTC time. Note that you don't call the now function, you just pass the function itself. That's the key difference.
You need to use a factory function for that.
var currDate(){
return function(){
return moment.utc();
}
}
var SubFavoriteSchema = new Schema({
user : { type: String, ref: 'Account'},
date : {type: Date, default: currDate()}
});

Mongoose - Query a nested property of Schema.Type.Mixed as a specified data type (Date)

I have a schema setup in Mongoose with
var MySchema = new Schema({
data: {
type: Schema.Types.Mixed
}
});
My issue is that on this 'data' object i am storing a date value as a nested property, it all works fine until i try and do a find() query with Mongoose and search using the nested field. Because Mongoose doesn't know it is a Date it cant use the usual '$gte', '$lte' and similar operators im guessing because it sees that data as just a String.
One of my objects looks similar to this
{
title:"My object",
data:{
publishDate: "2016-07-12T05:00:48.985Z"
}
Is there anyway that i can explicitly tell Mongoose to expect the value to be a date so i can use '$gte' as an operator?
Model.find({
"data.publishDate":{
$gte:new Date()
}
})
Turns out i had to strictly type the value as a date before saving to the database. Otherwise the date operators '$gte', '$lte' etc would not work.
Solution is to do this
{
title:"My object",
data:{
publishDate: new Date("2016-07-12T05:00:48.985Z")
}
At this point i don't believe you can type the data dynamically when running a query.

MongoDB date index

I am using node.js and mongodb for my small application and I want to index my document by date object. For Example
var MySchema = new Schema({
created_at: { type: Date, default: Date.now }
});
myschema.index({created_at: -1});
But how I understand, each object will have nearly unique create_id field. Wouldit work well ? and would this method give me effect. If you can, please also send me any articles about mongodb date indexing.

Resources