How to create routes with unique ids in NodeJS - node.js

So i am working on a project with node, express, mongoose en mongodb. I am able to create/save a topic to the db. but when the topic is saved/created i want to redirect the user to the topic details page of that created topic (so basically every created topic has its own unique url based of the id, like so -> localhost:3000/topicdetail/id)
The problem with me is that upon redirecting i get an error saying: Error: Failed to lookup view "error" in views directory "/Users/Grace/Desktop/QA/views"
So my main question is am i redirect it correctly with its own unique id or am i doing something else wrong. Any help is welcome.
my code is the following:
var mongoose = require('mongoose');
var Topic = require('../models/topic');
var db = require('../config/database');
var express = require('express');
var router = express.Router();
// render the start/create a new topic view
router.get('/', function(req, res) {
res.render('newtopic');
});
// save topic to db
router.post('/',function(req, res, next){
console.log('The post was submitted');
var topic = new Topic
({
"topicTitle": req.body.topicTitle,
"topicDescription": req.body.topicDescription,
"fbId": req.body.userIdFB,
"twId": req.body.userIdTW
})
topic.save(function (err, topic)
{
if(err){
return next(err)
console.log('Failed to save the topic to the database');
}
else
{
console.log('Saved the topic succesfully to the database');
// each topic has its own unique url
res.redirect('/topicdetail/{id}');
}
})
});
module.exports = router;

Calling res.redirect('/topicdetail/{id}'); won't insert any ID. Express won't reformat the string. It takes your defined redirect, in this case /topicdetail/{id}and performs it. Just like you would insert it into your browser.
To redirect your detail view you could do something like:
res.redirect('/topicdetail/' + topic._id); and replace topic.id with something like your document ID or another identifier.
Just a reminder: Your detail route needs a param in the route definition. Example: app.get('/verification/:token', users);. The :token is your param. More about in the routing guide.

Related

Get the count of Javascript object in jade from mongoose/node data

I have a node app which is tied to a mongo database and has routing with express and templates generated by Jade. Using express I am getting a list of all users using the following function:
/* GET users listing. */
router.get('/', function(req, res) {
User.find({}, function(err, users) {
var userMap = {};
users.forEach(function(user){
userMap[user._id] = user;
});
res.render('page', {
users : userMap
})
});
});
In my jade view I can display the users easily using:
each user in users
li= user.username
But I also want to get a count of the obj coming back and display that data on the page. I have tried #{users.size} and {users.length} as well as a few other variations to no avail. I am not sure what I am doing wrong. Do I need to add a count method to the model?
your variable users is an object not a array try
Object.keys(users).length

Retrieve unique ID from MongoDB using Express.js

I'm fairly new to MongoDB. My current code is as follows:
var app = express();
app.post('/myDB', function(req, res) {
console.log('POSTed data');
db.myDB.insert(req.body, function(err, doc) {
console.log(err);
res.json(doc);
});
})
I know that when data is inserted into MongoDB, a unique _id key:value pair is created. I would like to have access to this unique id upon data insertion.
But from what I know currently (admittedly not a whole lot), I would have to do an app.get('/myDB/:id')... (Or something similar) in order to access that unique identifier. Is there a way to do this without having to make an extra http request?
In MongoDB, with the Node.js driver, you can get the inserted id from the callback function's second parameter. The syntax is:
collection.insert(docs[[, options], callback])
where docs is a single document object or an array of documents, options is an options object and callback is a callback function to run after the record is inserted. The second paramter returns an array of documents inserted.
Thus you can retrieve the inserted id this way:
var app = express();
app.post('/myDB', function(req, res) {
console.log('POSTed data');
db.myDB.insert(req.body, {w:1}, function(err, doc) {
console.log("Record added as "+ doc[0]._id);
res.json(doc);
});
You can read more on the docs here.

I can display all items in my MongoDB collection, but can't save to it: "undefined"

I am relatively new to Node.js, currently, I'm trying to make a Q&A app, the following functionalities are relevant to my question and what I have to make.
List all discussions from MongoDB (this works).
Add a discussion with properties: author, title, body through a form to Mongodb.
Upon creating the new discussion, be redirected to a detail page of the newly made discussion.
This is my MongoDB structure: mongodb://localhost/Diskussrdb
The name of the collection is "discussions".
Currently, I am able to view all of my database records on localhost:3000/discussions
The page with the form for creating a new discussion is located at localhost:3000/discussions/create
FIXED: However, pressing the submit button on the /create page doesn't do anything. I've been staring myself blind at tutorials online but I can't find anything that helps me out.
FIXED: New question: The submit now works, but returns a 404 on the adress "localhost:3000/submit". I added a console.log to the /submit router.post but it doesn't display in my prompt.
The submit works, and goes to LH:3000/discussions/submit, but it seems my app cannot find my collection. However, LH:3000/discussions lists all items currently in my MongoDB (Diskussr, collection: discussions), so it has to be linked correctly, somehow.
A console.log of the collection also returns "undefined".
This is the error: "Cannot call method 'insert' of undefined
**
These are my code files:
discussions.js -- /routes
var mongoose = require('mongoose');
var express = require('express');
var router = express.Router();
var Discussion = require('../models/discussions');
router.get('/', function(req, res, next){
// alle db records uitlussen, op render alldiscussions
var db = req.db;
Discussion.find({},{},function(e,docs){
res.render('all_discussions', {
"all_discussions" : docs
});
console.log(docs);
});
});
router.get('/create', function(req, res, next){
res.render('add_discussion', {title: 'Diskussr'});
});
router.post('/submit', function(req, res) {
//set DB
var db = req.db;
//form vals
var author = req.body.name;
var title = req.body.title;
var body = req.body.body;
//set collection
var collection = db.get('discussions');
//insert
collection.insert({
"author" : author,
"title" : title,
"body" : body
}, function (err, doc) {
if (err) {
res.send("Database submit error");
}
else {
res.location("all_discussions");
res.redirect("all_discussions");
}
});
});
module.exports = router;
add_discussion.jade -- /views
extends layout
block content
h1 Start a discussion
p Start a discussion here on #{title} and help eachother out.
p Voeg hier uw vraag in:
form(action="/submit" method="post" name="submit_discussion")
input(id="name", placeholder="Your name" name="name")
br
br
input(id="title", placeholder="Brief summary of your problem." name="title")
br
br
input(id="body", placeholder="Explain your problem." name="body")
br
br
button(type="sumbit" id="submit" value="submit") Submit
br
discussions.js -- /models
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
//schema discussions
var DiscussionSchema = new Schema({
author: String,
title: String,
body: String,
category: String,
created: Date
},
{ collection : 'discussions' });
// model
var Discussion = mongoose.model('Discussion', DiscussionSchema, 'discussions');
// test functie: aanmaken vraag on load
// var firstDiscussion = new Discussion({author: "Testuser 1", title: "Testvraag via models"});
// console.log(firstDiscussion);
// //vraag saven
// firstDiscussion.save(function (err, firstDiscussion){
// if (err) return console.error(err);
// });
module.exports = Discussion;
My lecturer told me to post this to StackOverflow, since he is not willing to help me out himself.
Jade is whitespace sensitive, if you want html elements to be contained within another, say a form tag, you need to indent them.
block content
h1 Start a discussion
p Start a discussion here on #{title} and help eachother out.
p Voeg hier uw vraag in:
form(action="/submit" method="post" name="submit_discussion")
input(id="name", placeholder="Your name" name="name")
br
br
input(id="title", placeholder="Brief summary of your problem." name="title")
br
br
input(id="body", placeholder="Explain your problem." name="body")
br
br
button(type="sumbit" id="submit" value="submit") Submit
br
I would recommend using a debugger. To immediately see what is happening you can add a console output to the router.post to check that it is actually being called, like so:
router.post('/submit', function(req, res) {
console.log("POST received");
// etc
}
Further debugging:
Add this app.use() code anywhere in your app.js above your router.
app.use(function(req, res, next) {
console.log("Received: " + req.method + " at " + req.originalUrl);
next();
});
It'll get called everytime your app received a request, and then next(); moves on to your router. So you'll see:
Received: GET at /create
Received: POST at /submit
Database Issue
The issue with your database query is that you need to call insert on Discussion, not db.collection.get('Discussion');
Try:
Discussion.insert({
"author" : author,
"title" : title,
"body" : body
}, function (err, doc) {
if (err) {
res.send("Database submit error");
}
else {
res.location("all_discussions");
res.redirect("all_discussions");
}
});

node.js/express/mongoose noob issue

I just start to use node.js with express and mongoose, and I have a stupid question...
Somewhere in my routes.js file, I have the following section :
// DASHBOARD SECTION, GET MY GROUPS
app.get('/dashboard', isLoggedIn, function(req, res) {
var Group = require('../app/models/group'); //adding mongoose Schema
Group.find({"groupDetails.userId" : req.user._id})
.exec(function(err, myGroups) {
if (err)
res.send(err);
var myGroups = myGroups;
//console.log("myGroups: " + myGroups); // check with "heroku logs"
res.render('dashboard.ejs', {
user : req.user,
myGroups : myGroups
});
});
});
This code works. When someone browse the dashboard page, I receive "myGroups" which is an array with all the groups for the current logged in user.
Now, here is my question :
Actually when someone browse the dashboard page, I would like to make a second query (based on the exact same pattern) to get all groups and all files for the current logged in user.
Then I will send "user", "myGroups" and "myFiles" to the dashboard page.
How can I do that ?
I tried several things with no result so far... I think I'm a little bit lost in node.js callback functions :D
Thanks a lot for your help.
You have two options here:
1) deal with callback hell (callback inside callback inside...) to retrieve 3 sets of data. This way is least elegant and efficient
2) Use a library that will do the job asynchronously and have one callback when all the data is retrieved, you can use async library which is just awesome. In this case you will have just one callback in which you can access all the data you have fetched.
Here's what you can do with async in your case:
var async = require('async');
..........
app.get('/dashboard', isLoggedIn, function(req, res) {
var Group = require('../app/models/group'); //adding mongoose Schema
var User = require('../app/models/user'); //adding mongoose Schema
var Files = require('../app/models/files'); //adding mongoose Schema
async.parallel({
groups: function(callback){
Group.find(...).exec(callback);
},
users: function(callback){
Users.find(...).exec(callback);
},
files: function(callback){
Files.find(...).exec(callback);
}
}, function(err, results) {
if (err)
res.send(err);
var groups = results.groups;
var users = results.users;
var files = results.files;
res.render('dashboard.ejs', {
user : req.user,
myGroups : groups,
users: users,
files: files
});
});
});

How to loop over mongodb array with express and monk to create a page for each element?

I am building a web app with express, nodejs and monk. I am trying to create a page for each element of an array in my mongodb database.
That data is already in the collection called collections with the key coll_list like so:
{ "_id" : ObjectId("53dbaefd3d85d57492506f1f"), "coll_list" : [ "data_pagename1",
"data_pagename2", "data_pagename3" ] }
I thought it might be possible to loop over all the elements in coll_list with something like:
router.get('/index', function(req, res) {
var db = req.db;
var collection = db.get('collections');
collection.find( "coll_list" , function(e,docs) {
for (elems in docs) {
res.render(elems, {
elems : docs
});
}
});
});
Any suggestions or help/pointers on how to do this would be greatly appreciated.
Use req.params
router.get('/coll/:id',
function(req,res){
//access the id by req.params.id
//req.params.id will essentially be the _id of the document
//use it to obtain data from mongoDB and render the page using that data
//From the front end you make the call to /coll/<ObjectId> like
// /coll/53dbaefd3d85d57492506f1f and you get that id in req.params.id and use it to
//render data specific to that _id.
});
Thus, using a single route you would be able to create a page for every item in coll_list

Resources