How to get the data between two dates | NodsJs | MongoDB - node.js

I am trying to create an api to get the data between two dates in NodeJS. My database is mongoDB, my data looks like this
_id:ObjectId("60ff19125474fa0ec45c2d1a")
username:"abc"
Date:"2021-7-26"
TimeIn:"2:02 PM"
TimeOut:"2:02 PM"
_id:ObjectId("6101f4a4676d8b2b743a2d58")
username:"abc"
Date:"2021-7-27"
TimeIn:"2:02 PM"
TimeOut:"2:02 PM"
_id:ObjectId("6102e1357ad1ed20d4642db0")
username:"abc"
Date:"2021-7-28"
TimeIn:"2:02 PM"
TimeOut:"2:02 PM"
_id:ObjectId("6104717cb025c025e8b2d15e")
username:"abc"
Date:"2021-8-01"
TimeIn:"2:02 PM"
TimeOut:"2:02 PM"
i want to fetch the data between two dates, i create an api to fetch data by date (single), need some modification to fetch it between two dates.
here is api to fetch data by date:
fetchHistorybydate =(req,res)=>{
var HistoryList = []
User.find({"username":req.body.username, "leave":{ $exists : false} },function(err,data){
for(var i =1 ;i<data.length;i++){
var NDate = data[i].Date;
if(NDate==req.body.date){
HistoryList.push(data[i])
}
}
if(err)
{res.status(300).json("Error")}
else{
var token = jwt.sign({
data: 'foobar'
}, 'secret', { expiresIn: "30 minute"})
res.status(200).json({AccessToken: token,data:HistoryList})
}
})
}
for example:
let say there are two calender on frontend one is for Fromdate and second is for Todate, if user select date from Fromdate calender this 2021-7-26 and from Todate calender this 2021-7-28 then it will only fetch the records from these dates.
the output should be, according to above data
_id:ObjectId("60ff19125474fa0ec45c2d1a")
username:"abc"
Date:"2021-7-26"
TimeIn:"2:02 PM"
TimeOut:"2:02 PM"
_id:ObjectId("6101f4a4676d8b2b743a2d58")
username:"abc"
Date:"2021-7-27"
TimeIn:"2:02 PM"
TimeOut:"2:02 PM"
_id:ObjectId("6102e1357ad1ed20d4642db0")
username:"abc"
Date:"2021-7-28"
TimeIn:"2:02 PM"
TimeOut:"2:02 PM"
Please help me how to do this.

You have to update the store Date object in the Date parameter of your database. After that, you'll be able to query by two date ranges. Currently, your Date parameter is a string, but, you have to convert it to a Date object.
Here is the solution after converting into Date object:
fetchHistorybydate = (req, res) => {
var query = {
username: req.body.username,
Date: {
$gte: new Date(req.body.Fromdate).toISOString(),
$lte: new Date(req.body.Todate).toISOString()
},
leave: { $exists: false }
}
User.find(query, function (err, data) {
if (err) { return res.status(300).json("Error") }
else {
return res.status(200).json({ data: data })
}
})
}
Note: No need to loop through the entire array again after retrieving the data. Because we already query from our database with the $gte and $lte parameters. Where $gte means greater than or equal and $lte means less than or equal.
You can also use $gt (greater than) and $lt (less than).

Related

how to upload current date in mongoose schema when saving it?

I want to update the current date in yyy-mm-dd form so i can query it later but i m unable to insert date in the required format.here what i had did till
const sampleSchema = new mongoose.Schema({
username:String,
date:{
type:Date
}
});
const Sample = new mongoose.model("Sample", sampleSchema);
let currentDate=new Date
const sample = new Sample({
username:req.body.username,
date:currentDate.toISOString().split("T")[0]
});
sample.save()
I'm getting this
{
"_id": {
"$oid": "61b5862c6ff7ff297ae97d0c"
},
"user": "username",
"date": {
"$date": "2021-12-12T00:00:00.000Z"
},
"__v": 0
}
I want date in yyy-mm-dd format.
Use moment.js to convert the ISO formatted date into normal formatted date YYYY-MM-DD Don't try to store your own formate of date on MongoDB because it creates problems in querying data based on date and time. So update it into ISO and then convert it into different formate at the backend
Converting ISO formate Date into YYYY MM DD
date = new Date('2013-08-03T02:00:00Z');
date = moment(date).format('YYYY MM DD'); //result 2013 08 03
Converting YYYY MM DD formate into IOS formate
date = new Date('2013-08-03');
date = moment(date).format();
Another thing users can do is to store data in the form of a string
and use $gt, $gte, $lte and $lt operators for queries

ExpressJS: Mongoose query on ISO DATE based on todays date yyyy-mm-dd

I have date something like this
"createdAt": "ISODate('2021-07-07T06:41:46.000Z')"
I have written below mongoose query to fetch records for today. But below query fetched empty.
let meeting = await Meeting.find({
createdAt : {$lt: new Date().toISOString(),$gte: new Date().toISOString()}
});
I have tried below one more way with static date, it worked. I want to fetch data on dynamic todays date.
let meeting = await Meeting.find({
createdAt : {
'$eq': new Date('2021-07-07T06:41:46.000Z')
}
});
Can someone help me on this
I'm assuming the type of "createdAt" field is Date in Mongoose schema (you should convert to Date if it wasn't the case).
Logic
When you want to filter documents on a specific day, you can use the condition:
0:00 the day <= createdAt < 0:00 the following day
For example, to filter meetings on 07/07/2021, the condition will be:
0:00 07/07/2021 <= createdAt < 0:00 08/07/2021
Coding
With that logic in mind, the code is pretty straightforward:
let today = new Date();
today.setHours(0,0,0,0); // set to 0:00
let tomorrow = new Date(today)
tomorrow.setDate(tomorrow.getDate() + 1)
let meeting = await Meeting.find({
createdAt : {$gte: today, $lt: tomorrow}
});
When working with date/time values then I recommend the moment.js library. Could be this one:
let meeting = await Meeting.find({
createdAt : {
$gte: moment().startOf('day').toDate(),
$lte: moment().endOf('day').toDate()
}
});

Is there any query to find data between given dates?

I am sending the startDate and endDate in the URL and hits the query to find the data between startDate and endDate
var startDate = res.req.query.startDate ? moment(res.req.query.startDate, 'YYYY-MM-DD').valueOf() : null
var endDate = res.req.query.endDate ? moment(res.req.query.endDate, 'YYYY-MM-DD').valueOf() : null
if (startDate && endDate) {
query.dispatchDate = { $gte:startDate , $lte: endDate }
}
You did not clearly asked your question but i am suggestion you a solution what i understand.
In order to find data between 2 dates first you must add a field in db to track when the record is entered let suppose you have a collection named items and field to track when data is enter is created_date then you can find data between 2 dates like
items.find({
created_at: {
$gte: ISODate("2019-01-21T00:00:00.000Z"),
$lt: ISODate("2019-01-28T00:00:00.000Z")
}
})
for more details shHow to find objects between 2 dates in mongodb

Nodejs Mongodb Fetch data between date

I have saved my date as timestamp, using the below logic:
var timestamp = Math.floor(new Date().getTime()/1000);
timestamp =145161061
Can any one help me out with the query?
I need to find records between dates and my date is stored in timestamp format as shown above.
If you have specified the type of the field to be date, then even if you store the date by giving the time stamp, it will get stored as Date.
To do a range query on date you can simply do something like this:
db.events.find({"event_date": {
$gte: ISODate("2010-01-01T00:00:00Z"),
$lt: ISODate("2014-01-01T00:00:00Z"),}})
But then if you have specified it as Number, then you can simply do a range query on the number like this :
db.events.find({"event_date": {
$gte: 145161061,
$lt: 145178095,}})
You can try kind of this query:
var startTime = 145161061;
var endTime = 149161061;
Books.find({
created_at: {
$gt: startTime,
$lt: endTime
}
});

MongoDB/Mongoose querying at a specific date?

Is it possible to query for a specific date ?
I found in the mongo Cookbook that we can do it for a range Querying for a Date Range
Like that :
db.posts.find({"created_on": {"$gte": start, "$lt": end}})
But is it possible for a specific date ?
This doesn't work :
db.posts.find({"created_on": new Date(2012, 7, 14) })
That should work if the dates you saved in the DB are without time (just year, month, day).
Chances are that the dates you saved were new Date(), which includes the time components. To query those times you need to create a date range that includes all moments in a day.
db.posts.find({ //query today up to tonight
created_on: {
$gte: new Date(2012, 7, 14),
$lt: new Date(2012, 7, 15)
}
})
...5+ years later, I strongly suggest using date-fns instead
import endOfDayfrom 'date-fns/endOfDay'
import startOfDay from 'date-fns/startOfDay'
MyModel.find({
createdAt: {
$gte: startOfDay(new Date()),
$lte: endOfDay(new Date())
}
})
For those of us using Moment.js
const moment = require('moment')
const today = moment().startOf('day')
MyModel.find({
createdAt: {
$gte: today.toDate(),
$lte: moment(today).endOf('day').toDate()
}
})
Important: all moments are mutable!
tomorrow = today.add(1, 'days') does not work since it also mutates today. Calling moment(today) solves that problem by implicitly cloning today.
Yeah, Date object complects date and time, so comparing it with just date value does not work.
You can simply use the $where operator to express more complex condition with Javascript boolean expression :)
db.posts.find({ '$where': 'this.created_on.toJSON().slice(0, 10) == "2012-07-14"' })
created_on is the datetime field and 2012-07-14 is the specified date.
Date should be exactly in YYYY-MM-DD format.
Note: Use $where sparingly, it has performance implications.
Have you tried:
db.posts.find({"created_on": {"$gte": new Date(2012, 7, 14), "$lt": new Date(2012, 7, 15)}})
The problem you're going to run into is that dates are stored as timestamps in Mongo. So, to match a date you're asking it to match a timestamp. In your case I think you're trying to match a day (ie. from 00:00 to 23:59 on a specific date). If your dates are stored without times then you should be okay. Otherwise, try specifying your date as a range of time on the same day (ie. start=00:00, end=23:59) if gte doesn't work.
similar question
You can use following approach for API method to get results from specific day:
# [HTTP GET]
getMeals: (req, res) ->
options = {}
# eg. api/v1/meals?date=Tue+Jan+13+2015+00%3A00%3A00+GMT%2B0100+(CET)
if req.query.date?
date = new Date req.query.date
date.setHours 0, 0, 0, 0
endDate = new Date date
endDate.setHours 23, 59, 59, 59
options.date =
$lt: endDate
$gte: date
Meal.find options, (err, meals) ->
if err or not meals
handleError err, meals, res
else
res.json createJSON meals, null, 'meals'
i do it in this method and works fine
public async getDatabaseorderbyDate(req: Request, res: Response) {
const { dateQuery }: any = req.query
const date = new Date(dateQuery)
console.log(date)
const today = date.toLocaleDateString(`fr-CA`).split('/').join('-')
console.log(today)
const creationDate = {
"creationDate": {
'$gte': `${today}T00:00:00.000Z`,
'$lt': `${today}T23:59:59.999Z`
}
};
`
``
Problem I came into was filtering date in backend, when setting date to 0 hour, 0 minute, 0 second, 0 milisecond in node server it does in ISO time so current date 0 hour, 0 minute, 0 second, 0 milisecond of client may vary i.e. as a result which may gives a day after or before due to conversion of ISO time to local timezone
I fixed those by sending local time from client to server
// If client is from Asia/Kathmandu timezone it will zero time in that zone.
// Note ISODate time with zero time is not equal to above mention
const timeFromClient = new Date(new Date().setHours(0,0,0,0)).getTime()
And used this time to filter the documents by using this query
const getDateQuery = (filterBy, time) => {
const today = new Date(time);
const tomorrow = new Date(today.getDate() + 1);
switch(filterBy) {
case 'past':
return {
$exists: true,
$lt: today,
};
case 'present':
return {
$exists: true,
$gte: today,
$lt: tomorrow
};
case 'future':
return {
$exists: true,
$gte: tomorrow
};
default:
return {
$exists: true
};
};
};
const users = await UserModel.find({
expiryDate: getDateQuery('past', timeFromClient)
})
This can be done in another approach using aggregate if we have timezoneId like Asia/Kathmandu
const getDateQuery = (filterBy) => {
const today = new Date();
const tomorrow = new Date(today.getDate() + 1);
switch(filterBy) {
case 'past':
return {
$exists: true,
$lt: today,
};
case 'present':
return {
$exists: true,
$gte: today,
$lt: tomorrow
};
case 'future':
return {
$exists: true,
$gte: tomorrow
};
default:
return {
$exists: true
};
};
};
await UserModel.aggregate([
{
$addFields: {
expiryDateClientDate: {
$dateToParts: {
date: '$expiryDate',
timezone: 'Asia/Kathmandu'
}
}
},
},
{
$addFields: {
expiryDateClientDate: {
$dateFromParts: {
year: '$expiryDateClientDate.year',
month: '$expiryDateClientDate.month',
day: '$expiryDateClientDate.day'
}
}
},
},
{
$match: {
expiryDateClientDate: getDateQuery('past')
}
}
])
We had an issue relating to duplicated data in our database, with a date field having multiple values where we were meant to have 1. I thought I'd add the way we resolved the issue for reference.
We have a collection called "data" with a numeric "value" field and a date "date" field. We had a process which we thought was idempotent, but ended up adding 2 x values per day on second run:
{ "_id" : "1", "type":"x", "value":1.23, date : ISODate("2013-05-21T08:00:00Z")}
{ "_id" : "2", "type":"x", "value":1.23, date : ISODate("2013-05-21T17:00:00Z")}
We only need 1 of the 2 records, so had to resort the javascript to clean up the db. Our initial approach was going to be to iterate through the results and remove any field with a time of between 6am and 11am (all duplicates were in the morning), but during implementation, made a change. Here's the script used to fix it:
var data = db.data.find({"type" : "x"})
var found = [];
while (data.hasNext()){
var datum = data.next();
var rdate = datum.date;
// instead of the next set of conditions, we could have just used rdate.getHour() and checked if it was in the morning, but this approach was slightly better...
if (typeof found[rdate.getDate()+"-"+rdate.getMonth() + "-" + rdate.getFullYear()] !== "undefined") {
if (datum.value != found[rdate.getDate()+"-"+rdate.getMonth() + "-" + rdate.getFullYear()]) {
print("DISCREPENCY!!!: " + datum._id + " for date " + datum.date);
}
else {
print("Removing " + datum._id);
db.data.remove({ "_id": datum._id});
}
}
else {
found[rdate.getDate()+"-"+rdate.getMonth() + "-" + rdate.getFullYear()] = datum.value;
}
}
and then ran it with mongo thedatabase fixer_script.js
Well a very simple solution to this is given below
const start = new Date(2020-04-01);
start.setHours(0, 0, 0, 0);
const end = new Date(2021-04-01);
end.setHours(23, 59, 59, 999);
queryFilter.created_at={
$gte:start,
$lte:end
}
YourModel.find(queryFilter)
So, the above code simply finds the records from the given start date to the given end date.
Seemed like none of the answers worked for me. Although someone mentioned a little hint, I managed to make it work with this code below.
let endDate = startingDate
endDate = endDate + 'T23:59:59';
Model.find({dateCreated: {$gte: startingDate, $lte: endDate}})
startingDate will be the specific date you want to query with.
I preferred this solution to avoid installing moment and just to pass the startingDate like "2021-04-01" in postman.

Resources