mongoose.js: finding data entries by day - node.js

Suppose this is your model:
var EventSchema = new Schema({
title: String,
startDate: Date,
endDate: Date
});
I would like to throw in a date (as simple as like '24-12-2012') and then retrieve every event that started or proceeded at that single day.
How do you do that?

Sure:
First read up on mongo query syntax for dates, here is a how-to for date ranges: http://cookbook.mongodb.org/patterns/date_range/
Then translate that mongo syntax into mongoose.
Event.where('startDate').lte(yourDate).exec(callback); //should do the trick
Now you just need to parse date strings to javascript dates. There are some cool libraries to do that, I believe that moment.js won't have a problem with that date string.
Oh, I forgot the last bit of magic: Put that query into a static method attached to your Event model, so from now on you can just call
Event.earlierThan(yourDate, callback); //Where your custom static is called 'earlierThan'.

Related

Is it possible to refer to "this" document in Mongoose?

I'm using Mongoose in Node.js, and I am wondering if it is possible to refer to the currently selected document using "this" or a similar mechanism. Here is the use case I'm looking for :
Mongoose Schema :
const mySchema = mongoose.Schema({
position: Number,
date: Number,
lastEventDate: Number
});
Let's say that, at some point in time, an event occurs.
For a document selected through its position, I want to update "lastEventDate" to the document's date.
Here is my dream code :
myModel.findOneAndUpdate(
{position: myPosition},
{$set: {
'lastEventDate': THISDOCUMENT.date
}}
);
Note : I'm using $set here because the actual code updates subdocuments...
Is there a built-in "THISDOCUMENT" reference such as the one I'm dreaming of, to do it all in a single query ?
Or do I have to first query the value before updating the document (two queries).
Couldn't find anything on the web, and I'm quite the newbie when it comes to using "this".
Thanks for any kind of help !
[EDIT :] Precisions about the objective :
I am in a situation where I only have the position "myPosition" to identify the correct document, and I want to set "lastEventDate" to the same value as "date" for that document.
My question is about efficiency : is it possible to perform the update in a single upload query ? Or do I have to first download the "date" value before uploading it back to the "lastEventDate" key ?
Gathering all the information provided, I will venture on a possible answer!
You could try something like:
Your schema JS file
const mySchema = mongoose.Schema({
position: Number,
date: Number,
lastEventDate: Number
});
mySchema.methods.doYourThing(){
this.lastEventDate=this.date; //it will set the lastEventDate
}
mongoose.model("myModel", MySchema, "mycollection")
Now, whenever you call doYourThing(), the action wanted will take place, you call it after you have a instance of the mode.
This is from my own code
const token = user.generateJwt(expirationDate); //send a token, it will be stored locally in the browser
it is inside a function that return an instance of user, and in the model User I have done a function called generateJwt like I have showed, and we have something like this:
return jwt.sign(
{
_id: this._id, //this is created automatically by Mongo
email: this.email,
name: this.name,
exp: parseInt(expiry.getTime() / 1000, 10), //Includes exp as UNIX time in seconds
level: this.level,
lastLogin: this.lastLogin,
failedLogin: this.failedLogin
},
process.env.JWT_SECRET
); // DO NOT KEEP YOUR SECRET IN THE CODE!
It returns all the information of the user!
Please, do not hesitate to add comments and feebacks, I am not sure it is what you want, but that is why I have understood your request.
Anothe option is using Virtuals, they also have access to this.

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.

Passing current time to Mongoose query

I've run into problem. I made field in my Mongoose schema with type "Date":
...
timeOfPassingQuestion: Date,
...
Now, I want to pass current time in hours, minutes, seconds and miliseconds and save it into that field. How should I format my Node variable so I can pass it without errors?
Edit: Also, I forgot to say that I wanna later see how much time user spent answering question by subtracting current time and time that I pulled from DB, timeOfPassingQuestion field.
This is the syntax to create a schema that supports a date field:
// Schema
{ //...
someDate: Date,
}
// date object that you can use whenever you decide to set it
var dateObj = new Date();
This will create a JavaScript date object that you can then pass into your Mongoose object for the date field.
Or, if you will always want it on creation, put it directly in your mongoose schema
{ //...
createdDate: { type: Date, default: Date.now },
}
In order to compare the time in the future, I suggest you use moment.js, then you can query the time difference like so:
moment(Model.createdDate).fromNow();
Sources:
Mongoose Schema
Moment.js fromNow

Reporting in mongodb

I have report generating in my first node application. I used mongodb and express. I have three collections: salary rule, Leave and Employee. I want to generate employees salary by using these collections.
I found phantomjs to export pdf. I used ejs template to generate html.
I got json values from the following scenario.
find Salary rule
find All Employees
find all Leaves by date range.
Match employees and leaves by employee id and calculate the salary.
put the result json into the array and generate html by ejs
export html to pdf by using phantomjs.
I am confused that this scenario could be hit performance and error-prone. I cannot find any suitable examples for exporting in node and mongodb.
My question is-
Is it bad idea to use mongodb in this scenario or is it normal flow?
Or do I need to change my mongodb collection schema?
Leave
var schema = new mongoose.Schema({
date: { type: Date, default: Date.now },
description: String,
type: String, // paid or unpaid
empName : String,
empId : String
});
Employee
var schema = new mongoose.Schema({
id: String,
name: String,
basicSalary: Number,
active: Boolean
});
Salary Rule
var schema = new mongoose.Schema({
totalHoliday: Number,
overtimeFee: Number,
unpaidLeaveFee: Number
});
IMO looks like exporting your data to a Relational Database could be easy to generate the report.
BUT if you still want to do this with MongoDB you could do a mapReduce.
https://docs.mongodb.com/manual/reference/method/db.collection.mapReduce/
your last two steps are the same but change the way that you get the data.

Querying by date, regardless time part

I want to show my blog posts, paginated by creation date. I will have a page for 5 posts written in 2012-10-01, a page for 11 posts written in 2012-10-03 and no page at all for 2012-10-02 (no posts written)
Each post document is stored with a creation date which is a datetime value, here's a mongoose snippet:
var postSchema = new Schema({
url: String,
creationDate: {type: Date, default: Date.now},
contenuto: String,
});
so it will have something like 2012-10-01 18:45:03... know what I mean.
In my code, I will create a
var searchDate = new Date(yy,mm,dd);
How can I use that for querying the posts collection, without considering the "time part" of creationDate?
I'm not sure this would always work:
Post.find({ creationDate:dataRicerca })
As per this post;
How do I resolve a year/month/day date to a more specific date with time data in MongoDB?
you can store the data separately (as well as the full date) in your schema for easier searching. You could also do this;
Post.find({Posted:{$gt: Date("2012-10-01"), $lt:Date("2012-10-02")}})
(updated to use Date() rather than ISODate() for better compatibility)

Resources