NodeJS / Express 4 - Sqlite3 - Storing rowset into variable - node.js

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
});
});
});
});

Related

Mongoose: $inc not working

I am not sure what the problem is, as I've read numerous examples.
Taken from what I was advised here in this StackOverFlow(Mongoose - Increment a value inside an array of objects), I changed the format of poll at ease to accommodate what was recommended.
So I was able to create a document format as so:
{
"_id": "584c4160b3b22e1bdad59bce",
"title": "Food",
"description": "test",
"labelOptions": {
"burger": 29,
"coffee": 44,
"pizza": 23
},
"date": "Dec 10, 2016",
"__v": 0
}
Here's what I have so far:
Poll Model
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const pollData = new Schema({
title: String,
description: String,
labelOptions: {},
date: String
})
module.exports = mongoose.model('PollData', pollData)
Using express and mongoose, here's what I have:
app.put('/polls/:id', function(req, res){
let id = req.params.id;
let labelOption = req.query.labelOption;
let query = `labelOptions.${labelOption}`
Poll.findByIdAndUpdate(
id,
{$inc: { query: 1 } },
function(err, document){
console.log(err)
console.log(document)
}
)
})
In my terminal, I see that console.log(document it receives the document I was looking for but it does not update the value at all.
Am I setting up the Model correctly? Or does Mongoose does not support template strings?
***update
This is snippet of how I am creating documents
let labelOptions = {}; <=== creating object literal to hold as placeholder
const title = req.body.title;
const description = req.body.description;
req.body.labelOptions.split(/,\s*/).map( prop =>{
labelOptions[prop] = 0 // set counter to default 0
})
const poll = new Poll({
title: title,
description: description,
labelOptions: labelOptions,
date: moment().format('MMM D, YYYY')
});
poll.save(function(err) {
if (err) { return next(err); }
res.json({ message : 'Poll added!'})
});
After doing some research across the internet, I found the reason why it wasnt working: You can't initialize objects with 'dynamic' keys.
Source: Mongoose update on a string variable not working?
By knowing that, it was just a simple solution to initialize an literal object as so:
let id = req.params.id;
let labelOption = req.query.labelOption;
let query = "labelOptions." + labelOption
let obj = {
[query] : 1
}
Poll.findByIdAndUpdate(
id,
{$inc: obj },
function(err, document){
console.log(err)
console.log(document)
}
)

Mongoose, geospatial query for users

I'm currently working with nodeJS, using express and mongoDB and mongoose for an ORM. When I create a User and save them to the database I would like to query their location and save it. This is what I am currently doing, I have a UserSchema and a location Schema.
My userSchema just has the location stored as a string and in the location Schema itself I have
var locationSchema = new mongoose.Schema({
name: String,
loc: {
type: [Number],
index: '2d'
}
});
mongoose.model('Location', LocationSchema);
And then in my controller, I have the following
import json from '../helpers/json;
import mongoose from 'mongoose';
var User = mongoose.model('User);
module.exports = function() {
var obj = {};
obj.create = function (req, res) {
var user = new User(req.body);
user.roles = ['authenticated']
user.location = getLocation(req);
user.save(function (err) {
if (err) {
return json.bad(err, res);
}
json.good({
record: user,
});
});
};
return obj;
function getLocation (req) {
var limit = req.query.limit || 10;
var maxDistance = req.query.distance || 1;
maxDistance /= 6371;
var coords = [];
coords[0] = req.query.longitude;
coords[1] = req.query.lattitude;
Location.findOne({
loc: {
$near: coords,
$maxDistance: maxDistance
}
}).limit(limit).exec(function (err, location) {
if (err) {
console.log(err);
}
return location.name;
});
}
};
I have also tried using location.find instead of findOne and returning locations[0].name.
The error is thrown says cast to the number failed for value undefined at loc.
Do I need to send the location data to the server from the client side? If so, is there a best method to implement this? I have heard of the HTML5 Geolocation API, but I have never utilized it.
Thank you!
!!! -- UPDATE --- !!
I have started using the Geolocation API on the client side to send this data to the server in the request. I am using angular on the client side like so
(function() {
'use strict';
angular.module('opinionated.authentication')
.controller('SignupController', SignupController);
/* #ngInject */
function SignupController ($state, appUsers, appToast) {
var vm = this;
vm.reset = reset;
vm.create = create;
vm.user = {
name: '',
username: '',
email: '',
password: ''
};
vm.location = {
lattitude: '',
longitude: ''
};
function create = (isValid) {
if (isValid) {
var user = new appUsers.single({
name: vm.user.name,
username: vm.user.username,
email: vm.user.email,
password: vm.user.password,
lattitude: vm.location.lattitude,
longitutde: vm.location.longitude
});
user.$save(function (response) {
if (response.success) {
appToast('Welcome to Opinionated, ' + response.res.record.name);
$state.go('authentication.wizard')
} else {
appToast(response.res.messsage);
}
});
} else {
appToast('Hmm... Something seems to be missing');
}
}
function getPosition() {
navigator.geolocation.getPosition(updatePosition);
}
function updatePosition (position) {
vm.location.lattitude = position.coords.lattitude;
vm.location.longitutde = position.coords.longitude;
}
getPosition();
....
I think it has something to do with how I am getting the coordinates now. My browser prompts me for permission to use my location, so I am at least requesting the data. However, I changed my User Schema to save the lat and long and neither of these values are being saved upon success.
I found my error. I did need to include the Geolocation API to get the users coordinates. I then just saved the coordinates to the database and am using mongo's geo service from there! Everything works fine now.

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!

How to search in sub doc

I have an angular-fullstack app generated from angular-fullstack yeoman generator and I have a Query Model as follows:
'use strict';
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
/**
* Discussion Question Schema
*/
var QuerySchema = new Schema({
date: {
type: Date,
default: Date
},
tags: [{
type: Schema.ObjectId,
ref: 'Tag'
}]
});
module.exports = mongoose.model('Query', QuerySchema);
var deepPopulate = require('mongoose-deep-populate')(mongoose);
and Tag has a field text. Now in my query controller I have to deep populate some other fields and paginate them so, I am trying something like this in the controller function:
exports.index = function(req, res) {
var escapeRegExpChars = function (text) {
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
};
require('paginate-for-mongoose');
var limit,page;
if(req.query.limit != undefined) limit = req.query.limit;
else limit = 10;
if(req.query.page != undefined) page = req.query.page;
else page = 1;
var queryObj = {};
if(req.query.searchText != undefined && req.query.searchText != '')
queryObj['title']= new RegExp(escapeRegExpChars(req.query.searchText), 'i');
var options = {
perPage:limit,
delta:2,
page:page
};
if(req.query.fold !=undefined && req.query.fold != '') queryObj["tags.text"] = req.query.fold;
var query = Query.find(queryObj).populate('tags','text').deepPopulate('user class user.class');
query.paginate(options,function(err, resp){
if(err) { return handleError(res, err); }
if(req.query.fold) console.log(resp.results);
return res.status(200).json(resp.results);
});
};
How do I search queries with tags.text value exactly as the req.query.fold value?
MongoDB doesn't support joins so to search on a linked doc you have to do it in two steps:
// First look up the _id of the tag
Tags.findOne({text: req.query.fold}, function(err, tag) {
if (tag) {
// Add a match in the doc's tags array to the tag's _id
queryObj.tags = tag._id;
var query = Query.find(queryObj)...
...
}
});

how to create a new collection automatically in mongodb

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.

Resources