how to create a new collection automatically in mongodb - node.js

my main issue is how do this architecture - if a user creates a new list in database and there is a separate collections for storing lists ,then i should redirect him when he want to access a specific list where he can store his contacts by assigning him some collection in database, now the problem comes for me, if there are 'n' lists of a specific user for saving his contacts by categorizing in to lists based on his need , then how should i implement this architecture any suggestions ? or there's a mistake with what i have done so far ? any corrections ?
i am using mongodb,nodejs with express framework
What i have so far done is manually i was able to create a new list and allocate a collection for it so that user can add his contacts in that list.
But creating collections manually for each and every list is not possible so i am searching for a method where we can automatically create a new collection on demand.
Is there any method to create n collection or n sub collections in mongodb ?
This is my js file for adding contacts in a collection , where i have stored those contacts in two separate list with separate collection for each list.
var express = require('express');
var router = express.Router();
var $ = require("jquery");
var mongoose = require('mongoose');
/* GET New User page. in list 1 */
router.get('/mylist', function(req, res) {
res.render('mylist', { title: 'Go To My-List' });
});
router.post('/delcontact', function(req, res){
console.log('Using delcontact');
var db = req.db;
var collection = db.get('golists');
console.log('Got this : ' + JSON.stringify(req.body));
var delcontact = req.body;
var emails = Object.keys(delcontact).map(function(k) { return delcontact[k] });
for(var z=0; z<emails.length; z++){
//console.log('email: \n' + emails[z]);
collection.remove({email: emails[z]},
function(err, doc, z) {
if (err)
res.send('delete unsuccessfull');
else {
console.log('Selected contacts deleted');
}
});
res.send({redirect: '/userlist2'});
var collection = db.get('golists');
};
});
/* POST to Add User Service */
router.post('/addusers', function(req, res) {
// Set our internal DB variable
var db = req.db;
// Get our form values. These rely on the "name" attributes
var firstName = req.body.firstname;
var lastName = req.body.lastname
var userEmail = req.body.useremail;
// Set our collection
var collection = db.get('golists');
// Submit to the DB
collection.insert({
"firstname" : firstName,
"lastname" : lastName,
"email" : userEmail
}, function (err, doc) {
if (err) {
// If it failed, return error
res.send("There was a problem adding the information to the database.");
}
else {
// If it worked, set the header so the address bar doesn't still say /adduser
res.location("mailinglist");
// And forward to success page
res.redirect("mailinglist");
}
});
});
/* GET Userlist page. */
router.get('/mailinglist', function(req, res) {
var db = req.db;
var collection = db.get('golists');
collection.find({},{},function(e,docs){
res.render('userlist2', {
"userlist2" : docs
});
});
});
/* this is for list 2 */
router.get('/mylist2', function(req, res) {
res.render('mylist2', { title: 'Go To My-List' });
});
router.post('/addusers2', function(req,res){
//Set our internal DB variable
var db = req.db;
// Get our form values. These rely on the "name" attributes
var firstName = req.body.firstname;
var lastName = req.body.lastname
var userEmail = req.body.useremail;
// Set our collection
var collection = db.get('golists2');
// Submit to the DB
collection.insert({
"firstname" : firstName,
"lastname" : lastName,
"email" : userEmail
}, function (err, doc) {
if (err) {
// If it failed, return error
res.send("There was a problem adding the information to the database.");
}
else {
// If it worked, set the header so the address bar doesn't still say /adduser
res.location("mailinglist2");
// And forward to success page
res.redirect("mailinglist2");
}
});
});
/* GET Userlist page. */
router.get('/mailinglist2', function(req, res) {
var db = req.db;
var collection = db.get('golists2');
collection.find({},{},function(e,docs){
res.render('mailinglist2', {
"mailinglist2" : docs
});
});
});
router.post('/delcontact2', function(req, res){
console.log('Using delcontact');
var db = req.db;
var collection = db.get('golists2');
console.log('Got this : ' + JSON.stringify(req.body));
var delcontact = req.body;
var emails = Object.keys(delcontact).map(function(k) { return delcontact[k] });
for(var z=0; z<emails.length; z++){
//console.log('email: \n' + emails[z]);
collection.remove({email: emails[z]},
function(err, doc, z) {
if (err)
res.send('delete unsuccessfull');
else {
console.log('Selected contacts deleted');
}
});
res.send({redirect: '/mailinglist2'});
var collection = db.get('golists2');
};
});
this is my file for creating new lists in some collection
router.get('/newlist',function(req,res){
res.render("newlist" ,{titile:'Add new list'}) ;
});
router.post('/addlist',function(req,res){
var db= req.db;
var listname=req.body.listname;
var collection=db.get("lists");
collection.insert({
"listname":listname
}, function (err,doc) {
if(err) {
res.send("There was a problem adding new list to database");
}
else {
res.location('lou');
res.redirect('lou');
}
});
});
router.get('/lou',function(req,res){
var db=req.db;
var collection=db.get("lists");
collection.find({},{},function(e,docs){
res.render('lou', {
"lou" : docs
});
});
});
router.get('/drop', function(req, res) {
res.render('drop', { title: 'Go To My-List' });
});
my jade file for this is
body
nav.navbar.navbar-default
.container-fluid
ul.nav.navbar-nav
li.active
a(href='/mailinglist')
| List 1
span.sr-only (current)
|
li
a(href='/mailinglist2')
| List 2
tbody
ul
p Import Contact From Your DB
a(href='/upload2') Go
table.table#stable
caption User Contact Details
|
thread
tr
th #
|
th FirstName
|
th LastName
|
th Email ID
|
each user, i in userlist2
tr(id=i)
td
input.contactID(type='checkbox')
td
| #{user.firstname}
td
| #{user.lastname}
td(id='email'+i)
| #{user.email}
button.btn.btn-danger#delete-button Delete Selected Contacts

First of all, this doesn't sound like a good idea. It would be much better when you have one collection for all lists of all users. The problem with having too many collections is that MongoDB doesn't offer any tools for selecting data from more than one collection at a time. So when you want to query data from multiple collections, you will have to perform multiple queries, which is very unperformant.
However, when you are determined to cling to this architecture, MongoDB automatically creates a collection when you insert data into a collection-name it doesn't know.

Related

How to save array of inputs to a child schema in a nested mongoose schema?

I am trying to save a survey which contains multiples questions. Each time I enter a question and the answers and click the save button it should push it to the question array and at last when I click the save survey button the whole question should be saved under the parent schema 'survey'.
How can I do this with nodejs and mongoose? What I tried is here....
Mongoose schema
var mongoose = require("mongoose");
var Schema = mongoose.Schema;
var SurveySchema = new Schema({
surveyname: String,
question : [{
que: String,
ans1: String,
ans2: String,
ans3: String,
ans4: String
}]
});
module.exports=mongoose.model('Survey',SurveySchema);
The js file where I save the inputs to the schema
var express = require('express');
var router = express.Router();
var survey = require('../models/QBank');
router.post('/', function(req, res, next){
new survey({
surveyname: req.body.sname,
for(var i=0;i<5;i++){
question.question.push({
que: req.body.que,
ans1: req.body.ans1,
ans2: req.body.ans2,
ans3: req.body.ans3,
ans4: req.body.ans4
});
}
}).save(function(err, doc){
if(err) res.json(err);
else
req.flash('success_msg', 'Question saved to QBank');
res.redirect("/CreateSurvey");
});
});
module.exports = router;
I am stuck here with my project.
You can use an atomic update method like findOneAndUpdate() for your post where you can specify the upsert option. If upsert is true and no document matches the query criteria, findOneAndUpdate() inserts a single document. Here that's where you can also use the native
$push operator to push the new question and answers to the question array, rather than using a loop when you can let mongo do all the work on the server.
The following example shows how you can refactor your code:
var express = require('express');
var router = express.Router();
var Survey = require('../models/QBank');
router.post('/', function(req, res, next){
Survey.findOneAndUpdate(
{ "surveyname": req.body.sname }, /* <query> */
{ /* <update> */
"$push": {
"question": {
"que": req.body.que,
"ans1": req.body.ans1,
"ans2": req.body.ans2,
"ans3": req.body.ans3,
"ans4": req.body.ans4
}
}
},
{ "upsert": true }, /* <options> */
function(err, doc){ /* <callback> */
if(err) res.json(err);
else
req.flash('success_msg', 'Question saved to QBank');
res.redirect("/CreateSurvey");
}
);
});
module.exports = router;
In the above, the fields and values of both the <query> and <update> parameters are created if the <update> parameter contains update operator expressions. The update creates a base document from the equality clauses in the <query> parameter, and then applies the update expressions from the <update> parameter.
var survey = require('../models/QBank');
var Survey = new survey();
var question = [];
question[0] = req.body.que;
question[1] =req.body.ans1;
// do for all
Survey.question = question;
survey.save(Survey, function(err, doc){})
First of all you need to populate your survey object when you enter question and answer and hit save button.Then you can use ajax form submit to send the data to the desired route.
Let's say the survey object is like the following
var randomSurvey = {
surveyname: "randomSurvey",
questions:[
{
que: "question1",
ans1: "answer1"
ans2: "answer2"
ans3: "answer3"
ans4: "answer4"
},
{
que: "question1",
ans1: "answer1"
ans2: "answer2"
ans3: "answer3"
ans4: "answer4"
}
]
}
And when you press the save survey button then your post route should be like this.
router.post('/', function(req, res, next){
//Grab your data here sent over ajax form submit
var randomSurvey = req.body.randomSurvey;
var newSurvay = new survey(randomSurvey);
newSurvay.save(function(err, doc){
if(err) {
//do something with err
}
else{
// do something with the result;
}
res.redirect("/your_redirect_url");
});
});
According to your description you may passed full question to save in DB.
Assumed you passed data in req.body with multiple question.
like:
{surveyname: 'your survay name', question: [{que:'q1',ans1:'a1',....},{que:'q2'..},{que:'q3',..}]}
If assumption is correct then can use like:
router.post('/path', function(req, res, next){
var newSurvay = new survey({
surveyname: req.body.surveyname,
question: req.body.question
});
newSurvay.save(function(err, doc){
if(err) res.json(err);
else
req.flash('success_msg', 'Question saved to QBank');
res.redirect("/CreateSurvey");
});
});

Connecting Node.js to MongoDB using monk

I am trying to store the data written in jade to be stored in MongoDB using monk, but it is neither storing the data nor prompting any error
connecting to MongoDB code: (p1 is the name of the database)
var mongo = require('mongodb');
var monk = require('monk');
var db = monk('localhost:27017/p1');
index.js code to store in DB:
/* GET New User page. */
router.get('/addnew', function(req, res) {
res.render('addnew', { title: 'Add New Theatre' });
});
/* POST to Add User Service */
router.post('/addnew', function(req, res) {
// Set our internal DB variable
var db = req.db;
// Get our form values. These rely on the "name" attributes
var theatrename = req.body.TheatreName;
var screen = req.body.Screen;
var latitude = req.body.Latitude;
var longitude = req.body.Longitude;
var city = req.body.City;
// Set our collection (Theatre is the name of the collection)
var collection = db.get('Theatre');
// Submit to the DB
collection.insert({
"TheatreName" : theatrename,
"Screen" : screen,
"Latitude" : latitude,
"Longitude" : longitude,
"City" : city,
}, function (err, doc) {
if (err) {
// If it failed, return error
res.send("Not adding into db.");
}
else {
// And forward to success page
res.send("Theatrelist");
}
});
});
module.exports = router;
This is my jade code:
extends layout
block content
h1= title
form#formAddUser(name="adduser",method="post",action="/adduser")
p Thearte Name:
input#inputName(type="text", name="ThearteName")
br
p Screen :
input#inputScreen(type="text", name="Screen")
br
p Latitude:
input#inputUserLat(type="text", name="Latitude")
br
p Longitude:
input#inputlong(type="text", name="Longitude")
br
p City:
input#inputCity(type="text", name="City")
br
br
button#btnSubmit(type="submit") submit
If I were you I will try to do this:
show in console that vars from "req.body.VAR" are send correctly.
For example
router.post('/addnew', function(req, res) {
console.log(req.body.Screen);
Then, I will try to add some data to the BD for example:
collection.insert({
"TheatreName" : "Fakename",
"Screen" : "Fakescreen",
"Latitude" : "0",
"Longitude" : "0",
"City" : "Fakecity",
}, function (err, doc) {
if (err) {
// If it failed, return error
res.send("Not adding into db.");
}
else {
// And forward to success page
res.send("Theatrelist");
}
});
If you can see the result in your BD, all is OK (else, is in connection or something similar).
I hope my answer will help you!

NodeJS / Express 4 - Sqlite3 - Storing rowset into variable

I'm trying to store the rowset from the query below into a variable so I can play it into the view and loop through it.
I'm getting results from the DB, and can console.log them in the db.each block, and I thought I could generate my JSON object below and then store it - but it's not setting it for some reason and var data = "" just returns an empty string.
I am a bit baffled as to why - does anyone know where I am going wrong please?
Thank you for taking the time to read.
var express = require('express');
var router = express.Router();
var db = require('../lib/db.js');
/* GET contacts listing. */
router.get('/', function(req, res) {
var data = "";
db.serialize(function() {
var rowset = db.each("SELECT b.forename, b.surname FROM contacts a, contact_attributes b WHERE a.contact_id = b.contact_id", function(err, row) {
data = ' { "'+row.contact_id+'" : [ { "forename" : "'+row.forename+'", "surname" : "'+row.surname+'" } ] } ';
});
});
res.render('contacts', {
title: "Contacts",
active: "contacts",
contacts: JSON.stringify(data)
});
});
module.exports = router;
The database query runs asynchronously, executing the callback function once the query returns. Therefore, res.render is called after data gets set to empty string, but before it gets set to the result set.
Also, there is no need to JSON.stringify a string that you have already built as JSON.
The code executes as follows:
var data = "";
db.serialize
var rowset = db.each
res.render
DB query returns.
db.each callback function executes, which sets data based on the result set.
Try this:
db.serialize(function() {
var rowset = db.each("SELECT forename, surname FROM contacts a, contact_attributes b WHERE a.contact_id = b.contact_id", function(err, row) {
var data = ' { "'+row.contact_id+'" : [ { "forename" : "'+row.forename+'", "surname" : "'+row.surname+'" } ] } ';
res.render('contacts', {
title: "Contacts",
active: "contacts",
contacts: data
});
});
});
});
or, avoid the manual JSON stringification:
db.serialize(function() {
var rowset = db.each("SELECT forename, surname FROM contacts a, contact_attributes b WHERE a.contact_id = b.contact_id", function(err, row) {
var data = {};
data[row.contact_id] = [
{
forename: row.forname,
surname: row.surname
}
];
res.render('contacts', {
title: "Contacts",
active: "contacts",
contacts: data
});
});
});
});

MongoDB collection.save() duplicating objects

I'm working on my first web dev project involving backend work, and i'm giving mongoDB a shot. I'm currently working on a simple admin panel where every user is listed, and by clicking on that user the admin can go in and manually edit their info, update, and return to the master user list to see the changes.
I'm trying to use the collection.save() method to update the existing users, but I've encountered a problem where, instead of just updating, it creates a duplicate copy of the document with a matching _id number. Here is an image illustrating what I mean, and here is all of my code for the update:
router.post('/updateUser', function(req, res) {
var db = req.db;
var collection = req.collection;
var userId = req.body.userId;
var djStatus = req.body.djStatus;
var access = req.body.access;
var firstName = req.body.firstName;
var lastName = req.body.lastName;
var email = req.body.email;
var phone = req.body.phone;
var studentStatus = req.body.studentStatus;
var macIdNum = req.body.macIdNum;
var iclass = req.body.iclass;
var gradYear = req.body.gradYear;
var show = req.body.show;
var blurb = req.body.blurb;
collection.save(
{
_id: userId,
djStatus: djStatus,
access: access,
firstName: firstName,
lastName: lastName,
email: email,
phone: phone,
studentStatus: studentStatus,
macIdNum: macIdNum,
iclass: iclass,
gradYear: gradYear,
show: show,
blurb: blurb
}, function (err, doc) {
if (err) {
res.send('there was a problem updating');
} else {
console.log(doc + ' doc');
res.location('admin/users');
res.redirect('admin/users');
}
});
});
I am really not sure why this is happening. any help would be much appreciated!
From the post, I'm not sure which mongodb driver you're using but save() is probably not used for updating a document in mongodb. There should be an update() function from the mongodb driver you are using. For example, with mongoskin driver, this is the syntax for insert/update:
collection.update(_id: userId, {$set: data}, {safe:true, upsert:true}, function (err, result) {
// check err and result and do something
});

Return mongojs query result from function

I made the function below for getting usernames from ids. It is not working well.
I can write console.log(result.first_name); within the query function, and the usernames shows up in my terminal, but not the browser. I tried adding “return 'something';” at the end of the function, to see if that showed up in the browser – It did. How can I write the function so that the query result is returned?
function (global function in app.js)
function usernameFromId(id, callback){
db.users.findOne({ _id: ObjectId(id.toString()) }, function(err, result) {
var first_name = result.first_name;
console.log(first_name); // names show up in the console…
callback(first_name);
});
};
page handler (in app.js)
app.get('/books', function(req, res){
function timeSince(dato){
moment.lang('nb');
return moment(dato).fromNow();
};
db.books.find().sort({ added:-1 }, function(err, docs) {
var books = docs;
db.activity.find().limit(9).sort({ time:-1 }, function(err, docs) {
var activity = docs;
res.render('books', {
books: books,
activity: activity,
timeSince: timeSince,
usernameFromId: usernameFromId
})
});
});
});
template (books.jade)
- each a in activity
p=usernameFromId(a.user_id, function(name){return name;})
No because of the asynchronous nature of JavaScript. I have added some comments to your code to indicate the actual order of execution. This is why you are getting the error.
function usernameFromId(id){
var id = id.toString(); // 1
db.users.findOne({ _id: ObjectId(id) }, function(err, result) {
var first_name = result.first_name; // 3
});
return first_name; // 2
};
Edit: you probably want something like the following
function usernameFromId(id, callback){
var id = id.toString();
db.users.findOne({ _id: ObjectId(id) }, function(err, result) {
var first_name = result.first_name;
callback(first_name);
});
};
Okay, I found a solution. Not sure whether it’s any good, but it works. No need for a function.
page handler (in app.js):
app.get('/books', function(req, res){
db.activity.find().limit(9).sort({ time:-1 }, function(err, docs) {
var activity = docs;
db.users.find(function(err, docs) {
var users = docs;
res.render('books', {
page_title:'books',
activity: activity,
users: users
})
});
});
});
template (books.jade):
- each a in activity
- for u in users
- if (a.user_id == u._id.toString())
| #{u.first_name}

Resources