saving to mongodb with mongoose fails but no error shown - node.js

Am creating a nodejs bookstore app. Books details which are strings/numbers/booleans are to be saved in MongoDB using mongoose while the book cover image is to be saved in an uploads folder in my root directory using multer.Here is my mongoose schema:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
//Creating schema and model
var BookDataSchema = new Schema({
title: String,
author: String,
isbn: String,
price: Number,
quantity: Number,
availability: Boolean,
description: String
});
var BookData = mongoose.model('BookData', BookDataSchema);
module.exports = BookData;
This is the code to perform the saving function:
router.post('/', function (req, res) {
var newBook = new BookData({
title: req.body.bkname,
author: req.body.bkauthor,
isbn: req.body.bkisbn,
price: req.body.bkprice,
quantity: req.body.bkquant,
description: req.body.bkdesc
});
newBook.save(function (err) {
if (err) {
console.log(err);
} else {
console.log(newBook);
console.log('Book Details saved successfully');
}
});
}, function(req, res) {upload(req, res, (err) => {
if (err) {
console.log(err);
res.render('admin', {
msg: err
});
} else {
console.log(req.file);
return res.render('admin');
}});}
);
The main problem is when I console.log(newBook) or console.log(result) or check in mongo shell all I see is { _id: 5b4fdba80420890764ce13bf, __v: 0 }, only the id that mongodb creates is displayed which means the other data is not saved and worse it does not proceed to the other callback function. Am not getting any error apart from this warning:
(node:1220) [DEP0079] DeprecationWarning: Custom inspection function on Objects via .inspect() is deprecated
I tested the code for saving the image excluding that for saving the other data and it worked fine. Kindly help on what could be the problem and also advise me on how I would ensure the admin page is rendered only after everything has been saved. See the whole project in_this_git_repo

Related

object referencing/mongoose-mongodb

I have been taking colt Steeles's web development bootcamp classes,so i am on the associations topic. tried writing code to do a one to many association via object referencing, the code appears thus
var mongoose= require("mongoose");
mongoose.connect("mongodb://localhost/blogApp_demo_2",{useNewUrlParser:true});
var postSchema= new mongoose.Schema({
title:String,
content:String
});
var post= mongoose.model("post",postSchema);
var userSchema = new mongoose.Schema({
name: String,
Email:String,
posts:[
{
type:mongoose.Schema.Types.ObjectId,
ref:"post"
}]
});
var user= mongoose.model("user",userSchema);
post.create(
{
title:"beauty in the lilies",
content: "there is so much to marvel in lilies"
}, function(err,post){
user.findOne({email:"deleomoarukhe#yahoo.com"}, function(err,foundUser){
if(err){
console.log(err);
} else{
foundUser.posts.push(post);
foundUser.save(function(err,data){
if(err){
console.log(err);
}else{
console.log(data);
}
});
}
});
});
but on trying to execute this code it gives me this error
TypeError: Cannot read property 'posts' of null
tried everything i can to get this code running, to no avail.
p.s the code was to add a further comment to an already existing user.

How can I sort and limit with Mongoose

I made an review app with Express and Mongoose. I have an review model like below:
var mongoose = require('mongoose');
var ReviewSchema = mongoose.Schema({
title: String,
description: String,
rating: Number
}, {
timestamps: true
}
);
module.exports = mongoose.model('Review', ReviewSchema);
In my controller I just get all reviews list as below. But now I want to get a list with 10 recently reviews & sort by (orderby timestamps). How can I do it with mongoose? Please help me! I am a newbie with NodeJS and Mongodb.
exports.findAll = function(req, res) {
console.log("Fetching Review...")
// Retrieve and return all reviews from the database.
Review.find(function(err, reviews){
if(err) {
console.log(err);
res.status(500).send({message: "Some error occurred while retrieving Review."});
} else {
res.send(reviews);
}
});
};
Thanks you so much
This should work for you:
Review.find()
.sort({_id: -1})
.limit(10)
.then(reviews => {
console.log(reviews)
});
you can try like this :
Review.find({}, function(err,reviews){}).sort({_id: -1}).limit(10);

Mongoose NodeJS Schema with array of ref's

I know there is allot's of answers about it but still I didn't quite get the idea.
I have CourseSchema:
const CourseSchema = new Schema({
course_name: String,
course_number: {type: String, unique : true },
enrolledStudents:[{
type: mongoose.Schema.Types.ObjectId,
ref: 'Student' }]
});
And a StudentSchema:
const StudentSchema = new Schema({
first_name: String,
last_name: String,
enrolledCourses:[{
type: mongoose.Schema.Types.ObjectId,
ref: 'CourseSchema'
}]
});
I want to reffer enrolledStudents at CourseSchema with a student, and enrolledCourses at StudentSchema with a course.
router.post('/addStudentToCourse', function (req, res) {
Course.findById(req.params.courseId, function(err, course){
course.enrolledStudents.push(Student.findById(req.params.studentId, function(error, student){
student.enrolledCourses.push(course).save();
})).save();
});
});
but when posting I get an error:
TypeError: Cannot read property 'enrolledStudents' of null
Ok so after readying Query-populate I did that:
router.post('/addStudentToCourse', function (req, res) {
Course.
findOne({ _id : req.body.courseId }).
populate({
path: 'enrolledStudents'
, match: { _id : req.body.studentId }
}).
exec(function (err, course) {
if (err) return handleError(err);
console.log('The course name is %s', course.course_name);
});
});
And when i'm hitting POST on postman I get on the console:
The course name is intro for cs
but it is loading for ever and later on console I get:
POST /courses/addStudentToCourse - - ms - -
You are missing the populate instruction. For example:
see more about it here
Course.
findOne({ courseId : req.params.courseId }).
populate('enrolledStudents').
exec(function (err, course) {
if (err) return handleError(err);
console.log('The course name is %s', course.name);
});
It is working by using the ref field that "knows" how to populate withput using the push syntax. it is like a foreign key population.
Just call the populate method on the query and an array of documents will be returned in place of the original _ids. you can learn more on the internals of the populate methods in the official docs

Can't create a collection in MongoDB datatbase

Using this code to create a collection on MongoDB database hosted on mlab. But somehow it does not seems to be working. Is there something I am missing in this code? .save() function does not seem to be firing at all. Can it be due to my schema?
var mongoose= require('mongoose');
var Schema= mongoose.Schema;
app.use(express.static(__dirname+'/views'));
app.use(express.static(path.join(__dirname, 'public')));
//connect to mongo db database
mongoose.connect('mongodb://blaa:blaa#ds127132.mlab.com:27132/vendor');
//vendor schema
var vendorSchema= new Schema({
name:String,
image: { data: Buffer, contentType: String },
vendortype:String,
location: {
type: [Number], // [<longitude>, <latitude>]
index: '2d' // create the geospatial index
},
contactinfo:String,
description:String
});
//creating a model for mongoDB database
var Vendor= mongoose.model('Vendor',vendorSchema);
//just putting a sample record data
var imgPath = 'public/images/background.jpg';
var one = Vendor({
name: 'Justin Motor Works',
vendortype: 'Automobile',
contactinfo:'6764563839',
location: {
type:[23.600800037384033,46.76758746952729]
},
image: {
data: fs.readFileSync(imgPath),
contentType: 'image/jpg'
},
description: 'Motor workshop'
}).
save(function(err){
if(err)
throw err;
else {
console.log('create record failed');
}
});
mongoose.connect is an asynchronous function, you need to put your code inside a callback or promise.then(function(){.
Try this:
mongoose.connect('mongodb://blaa:blaa#ds127132.mlab.com:27132/vendor', function(error) {
if (error)
//handle error
//Your code
});
Or this:
mongoose.connect('mongodb://blaa:blaa#ds127132.mlab.com:27132/vendor').then(
() => {
//Your code
},
err => {
//Your error handling
}
);
Notice the error handling, it's important to know what caused the error for future debugging.
Also change the JSON structure of location when you are saving it as #NeilLunn said in the comments to something like this:
location: [23.600800037384033,46.76758746952729],
type in mongoose means actually defining the type of the key, and not a nested type key.

Mongoose saving for populate

I'm new to Mongoose and Nodejs developement in general and I've got a bit of confusion around how to properly set up saving my records. Here are my two schemas:
Download
var mongoose = require("mongoose");
var Schema = mongoose.Schema;
var downloadSchema = Schema({
title : String,
description : String,
_project : { type: Schema.Types.ObjectId, ref: 'Project' }
});
module.exports = mongoose.model('Download', downloadSchema);
Project
...
var projectSchema = Schema({
name : String,
url : String,
pwd : String,
_downloads : [{type: Schema.Types.ObjectId, ref: 'Download' }]
});
module.exports = mongoose.model('Project', projectSchema);
This appears to be working correctly. The documentation explains my use-case of saving a download and linking a project, but I'm not sure how to properly populate the Project._downloads. Here's what I've done:
Express route handler:
function createDownload(req, res) {
// the Project Id is passed in the req.body as ._project
var dldata = req.body;
Project.findOne({ _id : dldata._project }, function(err, project) {
var dload = new Download(dldata);
dload.save( function (err, download) {
project._downloads.push(download._id);
project.save( function(err){
var msg = {};
if(err) {
msg.status = 'error';
msg.text = err;
}else {
msg.status = 'success';
msg.text = 'Download created successfully!';
}
res.json(msg);
});
});
});
}
This seems overcomplicated to me. Am I supposed to be manually pushing to the ._downloads array, or is that something Mongoose is supposed to handle internally based on the schema? Is there a better way to achieve it so that I can do:
Download.find().populate('_project').exec( ...
as well as:
Project.findOne({_id : _projectId}).populate('_downloads').exec( ...
According to the mongoose docs there are 2 ways to add subdocs to the parent object:
1) by using the push() method
2) by using the create() method
So I think that your code can be a bit simplified by eliminating the operation of saving a new Download item:
function createDownload(req, res) {
var dldata = req.body;
Project.findOne({ _id : dldata._project }, function(err, project) {
// handle error
project._downloads.push(dldata);
project.save(function(err) {
// handle the result
});
});
}
or
function createDownload(req, res) {
var dldata = req.body;
Project.findOne({ _id : dldata._project }, function(err, project) {
// handle error
project._downloads.create(dldata);
project.save(function(err) {
// handle the result
});
});
}

Resources