I'm trying to retrieve data from a MongoDB with Node. Here is my code:
var MongoClient = require('mongodb').MongoClient;
var ObjectId = require('mongodb').ObjectId;
var url = 'mongodb://localhost:27017/test';
module.exports.get = function (req, res) {
//console.log(req.params.id)
//prints 1
var query = {};
query['id'] = req.params.id;
MongoClient.connect(url, function (err, db) {
db.collection('events')
.find(query)
.limit(1)
.next( function (err, event) {
if (err) {
res.status(500).send('Could not bring the resource requested!');
}
if (event) {
res.setHeader('Content-Type', 'application/json');
res.send(event);
}
else {
res.status(404).send('Can\'t find the resource you\'re looking for');
}
// db.close();
});
})
}
In my db, I have a document that has its own id field, different from _id.
Problem is with this line of code: query['id'] = req.params.id;
Using this, I get event = null.
But, when I change this to: query['id'] = 1;, I get the data that I'm looking for. I don't know where the problem is.
Managed to solve the problem. I was getting this because of req.params.id that is a String.
I used Number(req.params.id) and it's working.
Related
I'm using mongoose and express on my nodejs project.
Trying to get the data from here
app.get('/offers/:id', (req, res) =>{
//store the id from the url
var id = req.params.id;
//just a placeholder
var data = {title: "title", description:"description"};
//store the returned object in a variable
var oop = offers.findById(id, function (err, user) {
if(err){
return err;
}else{
title = user.title;
description = user.description;
this.obj = {
title:title,
description:description
}
console.log(obj)
return obj;
}
} );
console.log(oop)
res.render('single', {data:data});
});
so my idea is to grab the post id from the url, find it in the database, then display the title and description in the corresponding place on the ejs template, but for some reason I can't access the returned data, and what I get is a long list of objects that belongs to mongodb, without the presence of "title" or "description"
Try this, your code has couple of issues & also you need use .lean() to get raw Js objects rather than mongoDB documents :
app.get('/offers/:id', (req, res) => {
//store the id from the url
var id = req.params.id;
//just a placeholder
var data = { title: "title", description: "description" };
//store the returned object in a variable
offers.findById(id).lean().exec((err, user) => {
if (err) {
console.log(err);
res.send(err)
} else {
data.title = user.title;
data.description = user.description;
this.obj = {
title: title,
description: description
}
console.log(obj);
res.render('single', { data: data });
// (Or) res.render('single', { data: obj });
}
});
});
I just modified your code and added comments (all starting with "***").
app.get('/offers/:id', (req, res) =>{
//store the id from the url
var id = req.params.id;
//just a placeholder
var data = {title: "title", description:"description"};
//store the returned object in a variables
// var oop = ***no need for this, the data you want will be in the user variable.
offers.findById(id, function (err, user) {
if(err){
return err;
}else{
// ***this needs to be changed to...
// title = user.title;
// description = user.description;
// ***that...
data.title = user.title;
data.description = user.description;
// ***what's that for??
// this.obj = {
// title:title,
// description:description
// }
// ***this needs to be inside mongoose's callback
res.render('single', {data:data});
}
});
});
Having a hard time saving and modifying the result of a MongoJS query in NodeJS.
router.post('/getMySubjects', function (req, res) {
var data = [];
if (req.body.type == 'Professor') {
db.subjects.find({ contractorID: req.body.userId }, function (err, subjects) {
data = subjects; // SUBJECTS ARE NOW SAVED TO DATA SUCCESSFULLY
data.forEach(function(subject) {
db.faculties.find({ _id: mongojs.ObjectID(subject.subjectFor_faculty)}, function (err, faculty) {
subject.faculty = faculty; // BUT HERE I WANT TO ADD A FACULTY (object)
// BASED ON THE subjectFor_faculty (id)
// WHICH IS LOCATED IN EVERY (subject)
// ELEMENT IN DATA ARRAY
});
});
res.send(data); // THE DATA HERE IS UNMODIFIED
// SAME AS DATA ON LINE 6
});
}
});
I presume that I don't yet fully understand how the response works (btw the app is made with express framework), because when the data is first saved on line 6, the next step is sending the data, and only THEN the app goes goes into the forEach loop...
You are making async mongo queries. you have to make them work sync for getting right data. here's implementation using promises.
router.post('/getMySubjects', function (req, res) {
var data = [];
if (req.body.type == 'Professor') {
db.subjects.find({ contractorID: req.body.userId }, function (err, subjects) {
data = subjects;
var promises = [];
data.forEach(function(subject) {
var promise = new Promise(function(resolve, reject) {
db.faculties.find({ _id: mongojs.ObjectID(subject.subjectFor_faculty)}, function (err, faculty) {
resolve(faculty);
});
});
promises.push(promise);
});
Promise.all(promises).then(function(values){
for(var i = 0; i< values.length;i++){
data[i].faculty = values[i];
}
res.send(data);
});
});
}
});
I am trying to write a function that accepts the mongodb collection name as the paramater and return an instance of the collection so that it can be used to perform CRUD operartions. But when I am trying to return the instance of the collection it returns 'undefined' as the return statement is executed before the MongoClient.connect function finishes its execution.
module.exports.dbConnection = function(collectionName)
{
var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://127.0.0.1/test";
var collName;
MongoClient.connect(url, function(err, db)
{
var collName = db.collection(collectionName);
console.log(collName)
});
return collName;
}
Can I get assitance on how I can go about solving this issue.
Thanks
If you are using at least version 7.10 of Node you can accomplish this using async functions and promises.
// You can return a promise and resolve the promise once connected
module.exports.dbConnection = function dbConnection(collectionName) {
const MongoClient = require('mongodb').MongoClient;
const url = "mongodb://127.0.0.1/test";
return new Promise((resolve, reject) => {
MongoClient.connect(url, function (err, db) {
if (err) {
return reject(err);
}
resolve(db.collection(collectionName));
});
});
}
// You can then call the function within an async function (Node v7.10 and above)
async function fnThatCallsDbConnection() {
try {
const collName = await dbConnection('someCollection');
} catch(e){
// do something with error
}
}
Something additional you can do is cache your database connection so you don't need to connect every time - here's a way you could do it:
let cachedDB;
module.exports.dbConnection = function dbConnection(collectionName) {
const MongoClient = require('mongodb').MongoClient;
const url = "mongodb://127.0.0.1/test";
return new Promise((resolve, reject) => {
if (cachedDB) {
resolve(cachedDB.collection(collectionName));
} else {
MongoClient.connect(url, function (err, db) {
if (err) {
return reject(err);
}
cachedDB = db;
resolve(db.collection(collectionName));
});
}
});
}
The proper way to accomplish this is to use a callback. Accept a callback argument, and then pass your desired information to that function when the operation is complete.
module.exports.dbConnection = function(collectionName, cb)
{
var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://127.0.0.1/test";
var collName;
MongoClient.connect(url, function(err, db)
{
var collName = db.collection(collectionName);
cb(collName); // invoke our callback
});
}
And you use it like this:
dbConnection('collName', function (coll) {
console.log(coll);
// do something else with our collection
})
I am trying to create an api that will create a group with members in expressjs. This is how it works till now:
Make a post request with a JSON object in req.body, using which I will create a new group. If the members array of the req.body object contains member id, add it to the group members array, else create a new user and then add its id to the array.
Basically an existing user just gets added, new user will be created and then added. For this I need to loop through the members array in the req.body and check for an object.
But the code below doesn't seem to work properly. I am getting strange results for console.log(group_info.members);. I am expecting this to contain objects with id in an array, but getting random results. Something seems to be wrong in the foreach loop. Please help me figure it out.
var express = require('express');
var router = express.Router();
var Group = require('../models/GroupModel');
var User = require('../models/UserModel');
var async = require("async");
router.post('/', function (req, res, next) {
var group_members = [];
var group_info = req.body;
//see if a member object is sent, create user for that else just add the user id to group_members array
async.forEach(group_info.members, function (member, callback) {
if (typeof member == "object") {
//create new user and add the _id to members array
var user = new User(member);
user.save(function (err) {
if (err) return res.status(500).send(err);
var member_object = {id: user._id};
group_members.push(member_object);
}).then(callback);
} else {
var member_object = {id: member };
group_members.push(member_object);
callback();
}
}, function (err) {
//final call back
group_info.members = group_members; //replace the original array in request body with the new array of users
console.log(group_info.members);
var group = new Group(group_info);
group.save(function (err) {
if (err) return res.status(500).send(err);
res.json(group);
});
});
});
Looks like you made a mistake its eachSeries not forEach, so just replace :
async.forEach(group_info.members, function (member, callback)
with:
async.eachSeries(group_info.members, function (member, callback)
Update
As pointed out in the comments forEach is an alias for async each API, You can read the docs here,Thank You #megawac for pointing this out.
var group_members = [];
var group_info = req.body;
var todo = group_info.members.length;
var done = 0;
if(todo == 0)
{
return saveGroup(res, group_members);
}
else
{
group_info.members.forEach(function (member, index, array) {
if (typeof member == "object") {
//create new user and add the _id to members array
var user = new User(member);
user.save(function (err, savedObject) {
if (err || !savedObject)
{
return res.status(500).send(err);
}
else
{
var member_object = {id: savedObject._id};
group_members.push(member_object);
if(++done >= todo)
{
return saveGroup(res, group_info, group_members);
}
}
});
} else {
var member_object = {id: member };
group_members.push(member_object);
if(++done >= todo)
{
return saveGroup(res, group_info, group_members);
}
}
});
}
function saveGroup(res, group_info, group_members)
{
group_info.members = group_members; //replace the original array in request body with the new array of users
console.log(group_info.members);
var group = new Group(group_info);
group.save(function (err) {
if (err) return res.status(500).send(err);
res.json(group);
});
}
What is going wrong with my string parameter?
var express = require('express');
var app = module.exports = express();
var mongoose = require('mongoose');
var bodyParser = require('body-parser');
var braintree = require("braintree");
Schema = mongoose.Schema;
var user = require('../shared/userFunctions.js')
//register functions
app.register = function(api) {
api.get('get_client_token', generateClientToken);
api.get('find_customer', findCustomer);
api.post('checkout', checkout);
api.post('create_customer', createCustomer);
api.post('create_payment_method', newPaymentMethod);
}
The checkout function is where I call the local function with user.getuser
function checkout(request, response) {
var email = request.body.email;
var nonce = request.body.payment_method_nonce;
//var nonce = req.param("payment_method_nonce");
var amount = request.body.amount;
// Use payment method nonce here
gateway.transaction.sale({
amount: amount,
paymentMethodNonce: nonce,
}, function (err, result) {
if(err){
return response.send(500, "Checkout failed")
}
/* request.add({"amount": 10})
request = nonce;
newPaymentMethod(request);*/
/* return res.send(200, "Checkout Success")*/
});
user.getuser(email, function(u){
console.log("returning user: " + JSON.stringify(u))
return response.send(200, JSON.stringify(u))
})
}
If I hard core the email address into the mongoose query, it returns the user. What gives? Please give advice on my node async style. I am still new to it, but sometimes error first fucntions don't work and sometimes I need "next". The static email works but is my style the problem?
exports.getuser = function(email, res) {
var db = mongoose.connection;
mongoose.connect(process.env.MongoConnectionString);
db.on('error', function () {
});
db.once('open', function callback() {
console.log("Sucessfully Logged into mongo");
User.findOne({email:email}, function (err, user, next) {
if (err) {
mongoose.disconnect();
return next(err);
}
mongoose.disconnect();
console.log("Sending user response");
if(!user){
console.log("failed to get user")
return
}
return res(user);
});
});
EDIT
This function is responsible for calling the internal function. It seems to work exactly like the checkout function, except for its magical ability to work correctly.
function getUser(request, response) {
var email = request.param('email');
user.getuser(email, function(user){
return response.send(200, JSON.stringify(user))
})
};
Using a REST client so I assure you that body/params is not the problem. Thanks for the help thus far.
you can check your paratmeter in your api like this :
var password = req.body.passwordBrow || '';
var uidUser = req.body.uidUser || '';
and then check it :
if(password && uidUser){
// here you can log your parameters
}else{
// the parameter is undefined, so you need to check your request in the client
res.json({
status : "not_ok",
result : "empty_data",
resultType : serverConst.EmptyParams
});
}
hope it helps you.