Node.js is not giving any response and keep loading - node.js

If I am using this function I am getting proper response.
router.get('/', function(req, res, next) {
var products = Product.find();
res.render('shop/index', { title: 'Shopping-Cart', products: products });
});
If I am using below function my local server is not giving any response and keep loading.
router.get('/', function(req, res, next) {
Product.find(function (err, docs){
res.render('shop/index', { title: 'Shopping-Cart', products: docs });
});
});
Help me to solve this problem.

Try this. Add match object to find method.
router.get('/', function(req, res, next) {
Product.find({}, function (err, docs){
res.render('shop/index', { title: 'Shopping-Cart', products: docs });
});
});

The second one is simply wrong. This whole thing :
function (err, docs){
res.render('shop/index', { title: 'Shopping-Cart', products: docs });
}
is being passed to the find() method as a parameter.It makes absolutely no sense
Correct would be this:
Product.find().then(docs=>{
res.render('shop/index', { title: 'Shopping-Cart', products: docs })
}).catch(err=>console.log(err))

Since you haven't specified the database you are using, I'll assume something similar to MongoDB. The first parameter to the find operation must be a query object if any.
Documentation
So, you can tweak your code in any of the ways like this:
var products = await Product.find(); // Using async-await
res.render('shop/index', { title: 'Shopping-Cart', products: products });
Product.find({}, function(err, products) { // Using callbacks
res.render('shop/index', { title: 'Shopping-Card', products: products });
}
Product.find().then(function(products) { // Using Promises
res.render('shop/index', { title: 'Shopping-Card', products: products });
}

Related

Trouble passing mongoose variables to pug template through express

I have a User model through Mongoose, and I'm trying to create a simple CRUD API, starting with the Users part, problem is that my "index," and "create" routes seem to be working but the detail page won't seem to accept the variable being passed to it, and I can't render things on the page.
My User schema is very simple for now, just to get the API working (./models/user.js)
const userSchema = new Schema({
name: {
type: String,
maxlength: 50,
minlength: 2,
trim: true
}
})
The controllers for the routes that DO work look like this (./controllers/user_controller.js)
exports.index = function(req, res, next) {
User.find({}, (err, users) => {
res.render('userindex', {users: users})
})
}
exports.new = function(req, res, next) {
newUser = new User({ name: req.body.name })
newUser.save((err, user) => {
if (err) res.send(err)
res.redirect('/users')
})
}
exports.addUser = function(req, res, next) {
res.render('newuser')
}
The routes look like this so far (./routes/userRouter.js)
I do recognize that the routes for add and new are reversed, it'll be fixed.
userRouter.get('/', userController.index)
userRouter.get('/new', userController.addUser)
userRouter.post('/add', userController.new)
userRouter.get('/:id', userController.detail)
The only thing left is the broken controller: (./controllers/user_controller.js)
exports.detail = function(req, res, next) {
User.find({'_id': req.params.id}, (err, user) => {
if (err) res.send(err)
res.render('userdetail', {user: user})
})
}
And the template that won't seem to receive the data. (./views/userdetail.pug)
p #{user.name}
Find returns an array, so there's no user to template. Either template the first item on the collection:
res.render('userdetail', {user: user[0]})
or use .findOne instead.

Mongoose and Express, How can I get unique records from db?

In my database, I have 2-3 records with title (Article one).
How can I get only 1 result?
Following is my code that doesn't work,
app.get('/', (req, res) => {
Article.find.distinct(title, (err, title) => {
if(err){
console.log(err);
} else {
console.log(articles);
res.render('index', {
title: 'Articles',
articles: title
});
}
});
});
But if I use,
Article.find({}, (err, title)
it works, but I do not need objects because they are all unique
I tried this link
How do I query for distinct values in Mongoose?
But it does not work for me.
For example, I have records:
One, Two, One
But need output: One, Two
You need to use distinct operator with the desired property (here, title) passed as parameter like this,
app.get('/', (req, res) => {
Article.distinct('title', function(error, titles) { //see the use of distinct
if (err) {
console.log(err);
} else {
console.log(articles);
res.render('index', {
title: 'Articles',
articles: titles
});
}
});
});
The following query will return an array of title, all distinct.
Hope this resolves the issue.

two way navigation in a mongo one to n relashionship

I'm having hard times with the mongoose relashionship system.
Here are my schemes:
const mongoose = require('mongoose');
const RecipeSchema = mongoose.Schema({
Title: { type: String },
Description: { type: String },
Complaints: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Complaint' }]
});
const Recipe = mongoose.model('Recipe', RecipeSchema);
const ComplaintSchema = mongoose.Schema({
Recipe : { type: mongoose.Schema.Types.ObjectId, ref: 'Recipe' },
Message: { type: String }
});
const Complaint = mongoose.model('Complaint', ComplaintSchema);
And here are how I'm saving my data:
var recipeEntity = new Recipe({
Title: request.body.Title,
Description: request.body.Description
});
recipeEntity.save();
var complaintEntity= new Complaint({
Message: request.body.Message.trim(),
Recipe: mongoose.Types.ObjectId(request.body.Message.RecipeId);
});
complaintEntity.save();
So far, so good... at least to me!
And now, when I try to list the recipes with the complaints, I just got an empty array of complaints:
Recipe
.find()
.populate('Complaints')
.exec(callback);
And here is the json result:
[{
"Id": "595fe6f89d63700011ee144d",
"Title": "Chocolate Cake",
"Description": "aaaa bbb cc d"
"Complaints": []
}]
So, what am I missing here?
tks for your support
I am going to assume that you are not saving both recipe and complaint during the same call. That would not make any sense: everytime you make a complaint, you wouldn't make a recipe too.
When you create a complaint, you need to save its associated recipe's ObjectId AND also add/push the complaint's ObjectId into the associated recipe's complaints.
If you are following resource naming conventions, you would have something like:
// get recipes including complaints
app.get('/recipes', function (req, res) {
Recipe.find().populate('Complaints').exec(function (err, recipes) {
console.log(recipes);
});
});
// add recipe
app.post('/recipes', function (req, res) {
var recipe = new Recipe(req.body); // simplified
recipe.save(function (err) {
if (err)
return res.send(err);
res.send('ok');
});
});
// add complaint for recipe
app.post('/recipes/:recipeID/complaints', function (req, res) {
// we query recipe bc we need it after
Recipe.findById(req.params.recipeID, function (err, recipe) {
if (err)
return res.send(err);
if (!recipe)
return res.send('No recipe found');
// add complaint
var complaint = new Complaint(req.body);
complaint.Recipe = recipe._id; // add reference in one direction
complaint.save(function (err) {
if (err)
return res.send(err);
// update recipe
recipe.Complaints.push(complaint._id); // add reference in other direction
recipe.save(function (err) {
if (err)
return res.send(err);
res.send('ok');
});
});
});
})
I think this is a good read: many to many relationship with nosql (mongodb and mongoose).
OK, how I had to save the record in the reference too, I adopted this approach:
RecipeSchema.pre('remove', function(next) {
Complaint.remove({ "Recipe" : this._id }).exec();
next();
});
ComplaintSchema.pre('remove', function(next) {
Recipe.findById(this.Recipe).exec((error, item) => {
var index = item.Complaints.indexOf(item.Complaints.find(e => e._id == this._id));
item.Complaints.splice(index, 1);
item.save(() => { next(); });
});
});
ComplaintSchema.pre('save', function(next) {
Recipe.findById(this.Recipe).exec((error, item) => {
item.Complaints.push(this);
item.save(() => { next(); });
});
});
using this trigger/event available on the mongo schemas.
That worked perfectly!

Mongoose, creating a new model

I had model Product, he was added without problem to db "products"
router.post('/create', function (req, res, next) {
console.log(req.body);
var newProduct = {
title: req.body.name,
price: req.body.price,
description: req.body.description,
quantity: req.body.quantity,
// category: req.body.category
}
var product = new Product(newProduct);
product.save(function (err, product) {
if (err) {
res.status(404).json({
message: 'Can not create this product'
})
} else {
console.log('added');
res.send(product);
}
});
});
Now i have model Category i was created http.post and all is working, but I have no idea where this things sended by post are save in database mongo
router.post('/create', function (req, res, next) {
var newCategory = {
name: req.body.name,
description: req.body.description
}
var category = new Category(newCategory);
category.save(function (err, category) {
if (err) {
res.status(404).json({
message: 'Can not create this category'
})
} else {
console.log('added');
res.send(category);
}
});
});
Can someone exaplain me??
As far as mongoose automatically transforms your model name to plurual forms, it should be - categories.
Update:
If you still want your singular naming, you can try something like this:
const Category = mongoose.model('Category ', Category Schema, 'Category ');

get request only returns id and not the full element with nodejs

I am building a mean stack app.
When I use this :
router.get('/courses/:course', function (req, res) {
res.json(req.course);
});
I get back the full object. But when I do this :
router.get('/courses/:course/reviews', function (req, res){
res.json(req.course.reviews);
});
I only get back the reviews ID, not the full elements like I whished it did.
Any idea why ?
EDIT :
Answering questions :
here is router.param :
router.param('course', function (req, res, next, id) {
var query = Course.findById(id);
query.exec(function (err, course){
if(err) { return next(err);}
if(!course) {return next(new Error('can\'t find course'));}
req.course = course;
return next();
});
});
Course is a model :
var CourseSchema = new mongoose.Schema({
code: String,
name: String,
courseContentGrade: Number,
courseTeachingGrade: Number,
courseAverage: Number,
reviews: [{ type: mongoose.Schema.Types.ObjectId, ref: 'review'}]
});
You need to populate the review field using mongoose.populate().
Below is a revised router.param, note the addition of the populate method to the query.
router.param('course', function (req, res, next, id) {
var query = Course.findById(id).populate('reviews');
query.exec(function (err, course){
if(err) { return next(err);}
if(!course) {return next(new Error('can\'t find course'));}
req.course = course;
return next();
});
});
Documentation: http://mongoosejs.com/docs/populate.html

Resources