node.js not retrieving any data from mongodb - node.js

I am a beginner to node.js and trying to learn how to get data from mongodb to pass through node.js and display on the page.
I am learning it from a tutorial so follow those methods here.
https://www.youtube.com/watch?v=dSQ1CYLHWYM&index=6&list=PL55RiY5tL51rajp7Xr_zk-fCFtzdlGKUp
When I restart the server and load localhost it gets stuck and doesn't move forward and also does not show any errors in the terminal or the database or the console.
I am not sure why it is not showing any data in the view. My mongodb is working and listening to port 27017 and also if I go to mongod and do a db.products.find() I get to see all the data. Also if I just do it normally like var products = Product.find() it shows some data so basically there should be data coming in.
var express = require('express');
var router = express.Router();
var Product = require('../models/product');
/* GET home page. */
router.get('/', function(req, res, next) {
Product.find(function(err, docs){
console.log(docs);
var productChunks = [];
var chunkSize = 3;
for( var i= 0 ; i < docs.length ; i+= chunkSize) {
productChunks.push(docs.splice(i, i + chunkSize));
}
res.render('shop/index', { title: 'Shopping Cart' , products : productChunks});
});
});
module.exports = router;
And here is the Schema for the db
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var schema = new Schema({
imagePath : {type : String, required: true},
title : {type : String, required: true},
description : {type : String, required: true},
price : {type : String, required: true},
});
module.exports = mongoose.model('Product', schema);
Here is the index.hbs
{{# each products}}
<div class="row">
{{# each this}}
<div class="col-sm-6 col-md-4">
<div class="thumbnail">
<img class="img-responsive" src="{{this.imagePath}}" alt="...">
<div class="caption">
<h3>{{this.title}}</h3>
<p>{{this.description}}</p>
<div class="clearfix">
<div class="pull-left">${{this.price}}</div>
Add to cart
</div>
</div>
</div>
</div>
{{/each}}
</div>
{{/each}}
So I am not really sure how to tackle this problem. Since my local host is getting stuck, even if I restart the DB and server it still doesn't work.

Problem was that my app.js file was not completely configured well. I forgot to connect to mongoose. I solved the problem already.
Thanks everyone who commented on this.

Related

Mongoose schema not showing in view

I created a schema for the supports tickets I have to show on this view but, they are not actually showing. The data is showing in the console so I don't really understand the problem.
const mongosee = require ('mongoose');
const {Schema} = mongosee;
const AssignedTicketSchema = new Schema ({
name: { type: String, required: true},
pnumber: { type: String, required: true},
problem: { type: String, required: true},
support: {type: String, required: true},
date: { type: Date, default: Date.now}
});
module.exports = mongosee.model('AssignedTicket', AssignedTicketSchema)
These are the routes
router.post('/tickets/assign-tickets', isAuthenticated, async (req, res) => {
const {name, pnumber, problem, support}= req.body;
const newAssignedTicket = new AssignedTicket({name, pnumber, problem, support})
newAssignedTicket.user = req.user.id;
await newAssignedTicket.save();
req.flash('success_msg', 'Ticket assigned succesfully')
res.redirect('/tickets/assigned-tickets');
});
router.get('/assigned-tickets', isAuthenticated, async (req, res) => {
const assignedtickets = await AssignedTicket.find({user: req.user.id}).lean().sort({date: 'desc'});
res.render('tickets/assigned-tickets', {assignedtickets} );
});
And this is the view
<div class="row">
{{#each assignedtickets}}
<div class="col-md-3">
<div class="card">
<div class="card-body">
<h4 class="card-name d-flex justify-content-between align-items-center">
{{name}}
</h4>
<p>{{pnumber}}</p>
<p>{{problem}}</p>
<p>{{support}}</p>
</div>
</div>
</div>
{{else}}
<div class="card mx-auto">
<div class="card-body">
<p class="lead">There are no support tickets yet.</p>
Create a new support ticket
</div>
</div>
{{/each}}
</div>
From this line
res.redirect('/tickets/assigned-tickets');
Are you expecting to redirect to this method?
router.get('/assigned-tickets', isAuthenticated, async (req, res) => {
const assignedtickets = await AssignedTicket.find({user: req.user.id}).lean().sort({date: 'desc'});
res.render('tickets/assigned-tickets', {assignedtickets} );
});
Seems like the path is not an exact match.
Also, the redirect seems like is not sending the user id, probably you can send it as a parameter?
Check this other answers How do I redirect in expressjs while passing some context?
Express.js: Is it possible to pass an object to a redirect like it is with res.render?
how to pass data and redirect in express

Mongoose: push a string into array

I have a website where any logged-in user can leave a review for the shop.
So basically I have two schemas:
const journalSchema = new mongoose.Schema({
title: String,
category: String,
subcategory: String,
rating: Number,
review: [{type: String}],
link: String,
description: String,
});
const userSchema = new mongoose.Schema ({
username: String,
password: String,
journal: [{type: mongoose.Schema.Types.ObjectId, ref: 'Journal'}]
});
const Journal = mongoose.model("Journal", journalSchema);
const User = mongoose.model("User", userSchema);
form from the ejs file:
<div class="container my-3">
<h1>Compose</h1>
<form class="" action="/stats" method="post">
<div class="form-group">
<label for="review">Description</label>
<textarea id="review" class="form-control" name="journalReview" rows="5" cols="30"></textarea>
</div>
<button class="btn btn-primary my-2" type="submit" name="button">Publish</button>
</form>
</div>
post route:
app.post("/stats", function(req, res){
if(req.isAuthenticated()){
const favJournal = req.body.savedJournal;
const userId = req.user.id;
const userReview = req.body.journalReview;
User.findById(userId, function(err, foundUser){
Journal.findById(favJournal, function(err, foundJournal){
if(err){
console.log(err);
}
else{
if(foundUser){
foundJournal.review.push(userReview);
foundJournal.save(function(){
console.log(foundJournal);
});
foundUser.journal.addToSet(foundJournal);
foundUser.save(function(){
res.redirect("/favourite");
});
}
}
});
})
.populate('journal')
.exec(function(err, user){
if(err) return handleError(err);
});
}
else{
res.redirect("/login");
}
});
Every time I try to push review from the ejs file I keep getting this error:
events.js:353
throw er; // Unhandled 'error' event
^
TypeError: Cannot read property 'review' of null
at C:\Users\HelloThere\Desktop\miesto\app.js:337:24
at C:\Users\HelloThere\Desktop\miesto\node_modules\mongoose\lib\model.js:5065:18
at processTicksAndRejections (internal/process/task_queues.js:77:11)
Emitted 'error' event on Function instance at:
at C:\Users\HelloThere\Desktop\miesto\node_modules\mongoose\lib\model.js:5067:15
at processTicksAndRejections (internal/process/task_queues.js:77:11)
I tried different solutions from similar posts. Like mongoose methods: findOneAndUpdate and updateOne, but they just return null.
Instead of getting the shop and manipulating it with JavaScript code and then saving it back to the database, you could achieve this through findOneAnUpdate and $push operator.
For instance, this query
Shop.findById( shopId, (shop) => {
shop.products.push(product);
shop.save();
}
can be done through this query
Shop.findOneAndUpdate(
{ _id: shopId },
{ $push: {
products: product
}
})
$pop, $push, and $pull are very powerful tools to manipulate arrays in Mongoose. Take a look at the docs.
For the error you're getting, I think you're getting because you're passing a wrong journalId to findById. Check with MongoDB Compass if you do have a document with that id favJournal
I think I figured out the cause of the problem, I have two post forms in my ejs file, and since both forms have submit button with nothing differentiating them, only the first form gets called in the post route.

Adding a Comment to a Post without refreshing the page (like Instagram) Node.js, Express, Mongoose

I am trying to make a Instagram-like website and trying to add a comment to a post without refreshing the whole page, I am working with Node.js, Express, Mongoose. I am fairly new and I checked other similar questions but havent found anything that covered this very topic using the express framework.
I would be very thankful for your help!
Some of my code:
//Sending all the posts and their comments to the homepage
app.get("/", async function(req,res){
//get all posts from db
//this also somehow includes all the comments
const allPosts = await posts.find({}).populate('comments');
res.render("home", {posts: allPosts});
});
//comments being displayed under the image
<div class="container">
<h5 class="card-title"></h5>
<p class="card-text"><%= posts.description %></p>
<% posts.comments.forEach(function(posts){ %>
<p><strong><%= posts.comment.author %> - </strong><%= posts.comment.text %></p>
<% }) %>
</div>
//post Schema
var postSchema = new mongoose.Schema({
image: String,
description: String,
comments: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Comment"
}
]
});

Node.JS, Express & MongoDB Atlas:: Multiple Collections ejs

I have tried almost all the solutions but couldn't get this fixed.
I'm trying to get multiple collection of data (Mongodb Atlas) onto one ejs file. But I can't get data onto the rendered ejs sheet. But when I tested with locus I can see all the data received from the database up to res.render("/vendor/show"). But it is not passing onto ejs template.
I have three sets of data sitting on the mongo Atlas:
const vendorSchema = new mongoose.Schema({
name:String,
image:String,
imageId:String,
});
const newpromoSchema = new mongoose.Schema({
name:String,
image:String,
imageId:String,
vendor:String,
description:String,
sdate:String,
edate:String,
});
const neweventSchema = new mongoose.Schema({
name:String,
image:String,
imageId:String,
description:String,
vendor:String,
sdate:String,
edate:String,
});
router.get("/vendors/:id",function(req,res) {
var events={}; //Create Empty event Object
var promotions={}; //Create Empty promotion Object
var vendors={};//Create Empty vendor Objext
Promotion.find({},function (err,allPromotions) {
if (err) {
console.log(err);
} else {
//Find Collection And Assign It To Object
promotions=allPromotions;
}
});
Event.find({},function(err, allEvents) {
if (err) {
console.log(err);
} else {
events=allEvents;
}
});
Vendor.find({},function(err,allVendors){
if(err){
console.log(err);
}else{
vendors=allVendors;
//find order collection and passing it to ejs templates
res.render("vendors/show",{ event:events, promotion:promotions vendor:vendors});
}
});
});
Show.ejs code as
<%=vendor.name%>
<%=promotion.name%>
<%=event.name%>
You need to handle the async process. In your current code, there are three async processes. Please go through following the link you will definitely get an idea about it.
https://blog.risingstack.com/mastering-async-await-in-nodejs/
if you need more help Don’t hesitate to comment.
I managed to get all data using the below function. But now I have another issue, need to filter all the Promotions and Events by vendor But it doesn't filter.
Data Schema
const neweventSchema = new mongoose.Schema({
name:String,
image:String,
imageId:String,
description:String,
vendor:String,
sdate:String,
edate:String,
});
const Event = mongoose.model("Event",neweventSchema);
module.exports = Event;
//SCHEMA SETUP===============================================================================================================
const newpromoSchema = new mongoose.Schema({
name:String,
image:String,
imageId:String,
vendor:String,
description:String,
sdate:String,
edate:String,
});
//compile into a model
const Promotion = mongoose.model('Promotion',newpromoSchema);
module.exports = Promotion;
//SCHEMA SETUP===============================================================================================================
const vendorSchema = new mongoose.Schema({
name:String,
image:String,
imageId:String,
});
const Vendor = mongoose.model("Vendor", vendorSchema);
module.exports = Vendor;
Routes as below
router.get("/vendors/:id", function (req, res) {
Vendor.find({}, function (err, allVendors) {
if (err) {
console.log(err);
} else {
// //Find Collection And Assign It To Object
Event.find({}, function (err, allEvents) {
if (err) {
console.log(err);
} else {
Promotion.find({}, function (err, allPromotions) {
if (err) {
console.log(err);
} else {
//find order collection and passing it to ejs templates
res.render("vendors/show", {event: allEvents, promo: allPromotions, vendor: allVendors});
}
});
}
});
}
});
});
EJS Show page But It doesn't get filtered.
<!-- Trying to filter all the events by vendor if event's vendor name == vendor name then show on the show page -->
<%if(event.vendor === vendor.name){%>
<div class = "container-fluid">
<div class = "row">
<%event.forEach(function(events){%>
<div class="col-sm-6 col col-md-4 col-lg-3">
<div class="thumbnail">
<img src ="</%=events.image%>" class="rounded" width="304" height="236">
<div class="caption">
<h4><%=events.name%></h4>
<p class="font-italic font-weight-bold text-muted">
<%=events.vendor%>
</p>
<p><strong>Start Date</strong><%=events.sdate%></p>
<p><strong>End Date</strong><%=events.edate%></p>
</div>
<p>Event Details <br>
<%=events.description.substring(0,100)%>
</p>
<p>
Find More
</p>
</div>
</div>
<%})%>
</div>
</div>
<%}%>
<!-- //Trying to filter all the promotions by vendor if vendor name= to promotions's vendor name only show in the show page-->
<%if(promo.vendor===vendor.name){%>
<div class = "container-fluid">
<div class = "row">
<%promo.forEach(function(promotions){%>
<div class="col-sm-6 col col-md-4 col-lg-3">
<div class="thumbnail">
<img src ="<%=promotions.image%>" class="rounded" width="304" height="236">
<div class="caption">
<h4><%=promotions.name%></h4>
<p class="font-italic font-weight-bold text-muted"> <%=promotions.vendor%></p>
<p><strong>Start Date</strong> <%=promotions.sdate%></p>
<p><strong>End Date</strong> <%=promotions.edate%></p>
</div>
<p>
<%=promotions.description.substring(0,100)%>
</p>
<p>
Find More
</p>
</div>
</div>
<%})%>
</div>
</div>
<%}%>

How can I add/subtract data from a EJS template

I cant figure out how to substract data from an EJS template. This is my Schema:
var mongoose = require("mongoose");
var Schema = mongoose.Schema;
var InventorySchema = Schema({
name: [{type: String, required: true, unique: true}],
quantity: [Number],
code: [String],
price: [Number],
stock: [{type: Boolean, default: true}]
})
var Inventory = mongoose.model("Inventory", InventorySchema);
module.exports = Inventory;
The below is the main query to show all my data:
router.get("/", (req, res)=>{
InventoryModel.find({})
.then((inventory)=>{
console.log(inventory);
res.render("inventory/index", {inventory: inventory})
})
.catch((err)=>{
console.log(err);
})
})
And below is the form Where I want to add/subtract data from:
<div class="container">
<form action="/inventory" method="POST">
<label>Name</label>
<input type="text" name="itemName" placeholder="item name"><p/>
<label>Quantity</label>
<input type="number" name="quantity" placeholder="quantity"><p/>
<button>Create</button>
</form>
</div>
So here's what I'm trying to accomplish. Whatever number I enter in the quantity field, subtract that data from my mongodb database whenever I hit the create button (which is a POST)
Any help?
Thank you
You would need to do an update on the existing document and use the $inc operator.
Example:
# create query conditions and update variables
const conditions = { },
update = { $inc: { views: 1 }}; # inc accepts negative numbers
# update documents matching condition
Model.update(conditions, update)

Resources