MongoDB returning a lot of data - node.js

I am trying to grab all documents from my "chats" collection. When I loop through my results variable and console log item, I get a lot of data back. how can I query all objects and get just the document fields?
//create route
router.get('/', function(req, res) {
db.connect(url, function(err, db){
if(err){
console.log(err);
}else{
console.log("Connected");
}
getAllChats(db, function(data){
console.log(data);
});
});
res.render('index.jade');
});
var getAllChats = function(db, callback){
var collection = db.collection('chats');
var results = collection.find();
results.each(function(err, item) {
// If the item is null then the cursor is exhausted/empty and closed
console.log(item);
if(item == null) {
db.close(); // you may not want to close the DB if you have more code....
return;
}
// otherwise, do something with the item
});
callback(results);
}

You need a projection to achieve this.
https://docs.mongodb.com/manual/tutorial/project-fields-from-query-results/
var collection = db.collection('chats');
var results = collection.find(query, projection);
In your case query will be {};
Projection will be {FieldYouNeed: 1, fieldYouNeed: 1, ...};
Here is example
var results = collection.find({name: "developer"}, {_id: 0, name: 1, email:1});
In this case only name and email will be returned from DB.
Hope this helps.

Related

Can't access fields of MongoDB document in Node.Js

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

Saving MongoJS select result to an array in NodeJS and then modifying it

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

Node JS - Asynchronous when I want to display a list from Mongoose

I have a problem when I want to display a list of data from Mongoose (MongoDB) to my front-end in ejs
For example:
var User = require("./models/user");
var Houses = require("./models/house");
app.get("/", function(req, res){
var list_houses = [];
for(var i=0; i<req.user.city.length; i++)
{
Houses.find({'city': req.user.city[i]}, function(err, result){
if(err)console.log(err);
if(result){
list_houses = list_houses.concat(result);//add array result to array list_prices
}
});
}
res.render("/prices_houses",{list_houses: list_houses});
});
I found the module 'async', but neither does not work, my code was:
var User = require("./models/user");
var Houses = require("./models/house");
var async = require('async');
app.get("/", function(req,res){
var list_houses = [];
async.waterfall([
async.each(req.user.city, function(result, callback){
Houses.find({'city': result}, function(err, result){
if(err)console.log(err);
if(result){
list_houses = list_houses.concat(result);
}
});
});
], function(arg1, callback){
res.render("/prices_houses", {list_houses: list_houses});
});
});
When I want to display 'list_houses.length' in ejs, it shows this: 0
<%=list_houses.length%>
My schemas in mongoose are:
var User = new mongoose.Schema({
city : [String]
...
});
var House = new mongoose.Schema({
city: String
price: Double
});
I know that the problem is with Asynchronous, but I don't know how to solve it.
Please help me with this problem.
You're overcomplicating it, I think. Seems like you can just use the $in operator for this. Something along these lines:
Houses.find({'city': {$in: req.user.city}}, function(err, results){
if(err)console.log(err);
console.log(results); // this should be an array of all houses in all cities that the user has in their city array
});
Yes the problem with is asynchronous nature of nodejs. You can not use for loop as it will be over before any of the databse calls gave any result.
As Paul pointed out, you should use queries provided by mongo when you use array.
But this is a common pattern you can use if you need to do multiple databases calls.
var User = require("./models/user");
var Houses = require("./models/house");
app.get("/", function(req, res){
var list_houses = [];
var index = req.user.city.length;
function findHouses(i, arr, cb){
//databases call here
Houses.find({'city': arr.city[i]}, function(err, result){
if(err)console.log(err);
if(result){
cb(result);
} else{
cb(null);
}
});
}
findHouses(index--, req.user.city, function(result){
if(result && index>=0){
list_houses = list_houses.concat(result);
findHouses(index--, req.user.city);
} else if(index == 0){
res.render("/prices_houses",{list_houses: list_houses});
}
});
});
this code should work fine i have used call back
app.get("/", function(req, res){
function listhouses(cb){
var list_houses = [];
for(var i=0; i<req.user.city.length; i++)
{
Houses.find({'city': req.user.city[i]}, function(err, result){
if(err)console.log(err);
if(result){
list_houses = list_houses.concat(result);//add array result to array list_prices
}
});
}
cb(list_houses);
}
listhouses(function(list_houses){
res.render("/prices_houses",{list_houses: list_houses});
});
});

NodeJS Error with stock Mongodb Adapter: Connection Closed By Application

I'm having a weird issue with MongoDB. My database collection is closing, which I suppose is what it's supposed to do (I'm following along from the mongo boilerplate) BUT I see no reason why the docs would be null value. I've checked this every way I can think of, but I don't quite understand the cursor object.
Console.logging it seems to give me a bunch of native mongo properties ( which look like functions ie each, toArray, etc) so it seems right, but it's not a regular object with a data field that I can see.
After it hits that if block with the if(docs==null), the connection gets closed and it will not execute the each block in the else if.
Ideally if there was a way to help troubleshoot or figure out how to make this execute that would be great.
More background:
in the mongo shell I can ask for
use weather // no issues
and get the results of the data object which is 3000 records with an empty find();
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect('mongodb://localhost:27017/weather', function(err, db) {
if(err){
console.log("line 7" + err);
}
var query = {};
var projection = { 'State' : 1, 'Temperature' : 1 };
var cursor = db.collection('data').find(query, projection);
console.log("cursor" + cursor); // [object Object]
var state = '';
var operator = {'$set' : {'month_high' : true } };
cursor.each(function(err, doc) {
if (err) throw err;
if (doc == null) {
console.log("docs have value:" + doc); //NULL VALUE so will close on line 23
return db.close();
} else if (doc.State !== state) {
// first record for each state is the high temp one
state = doc.State;
db.collection('data').update( {'_id':doc._id}, operator, function(err, updated) {
if (err) console.log(err);
// return db.close(); ?
});
}
});
});
{ [MongoError: Connection Closed By Application] name: 'MongoError' } //doh
{ [MongoError: Connection Closed By Application] name: 'MongoError' } //doh
{ [MongoError: Connection Closed By Application] name: 'MongoError' } //doh
Figuring out when to call db.close() can be a bit messy. Here it is rewritten with find().toArray() plus some logic to test when you're updating the last matched doc. This works for me.
var MongoClient = require('mongodb').MongoClient;
var assert = require('assert');
var Q = require('q');
MongoClient.connect('mongodb://localhost:27017/weather', function(err, db) {
assert.equal(null, err);
var query = {};
var projection = { 'State' : 1, 'Temperature' : 1 };
var state = '';
var operator = {'$set' : {'month_high' : true } };
var promises = [];
db.collection('data').find(query, projection).toArray(function(err, docs) {
assert.equal(null, err);
docs.forEach(function(doc, index, arr) {
var deferred = Q.defer();
promises.push(deferred.promise);
if (null !== doc && state !== doc.State) {
db.collection('data').update( {'_id':doc._id}, operator, function(err, updated) {
assert.equal(null, err);
console.log("Updated "+updated+" documents.");
deferred.resolve();
});
} else {
deferred.resolve();
}
});
Q.all(promises).done(function() {
console.log("closing");
db.close()
});
});
});
EDIT: Added Q since db.close() was still called prematurely in some cases.

how to $set a mongoDB cursor in node.js?

I have a mongoDB collection which I want to add a field at random locations using $set, at least I am pretty sure its a $set. Correct me if I am wrong.
I am including code. Around the middle I include remarks of what I am trying to do:
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect('mongodb://localhost:27017/weather', function(err, db) {
// Also, what is the best way to handle err in this code?
//if(err) throw err;
var query = { };
var sortorder = {"State":1, "Temperature":-1}
var xx = null;
//var cursor = db.collection('data').find();
var cursor = db.collection('data').find().sort(sortorder);
cursor.each(function(err, doc) {
//if(err) throw err;
if(doc == null) {
return db.close();
}
if (xx == doc.State){
}else{
console.dir("New state -----------" + doc.State);
console.dir("Tempurature -----------" + doc.Temperature);
// !!!!!!!!!!!!!!!!!!!!!!!!!! this is the problem area.
//--- this is the part I am trying to figure out...
update_routine = $set:{"month_high---test001":true};
doc.update = update_routine;
// How do I do a $set operation on a mongoDB cursor. which I have here.
xx = doc.State;
// add the field
//doc.update();
}
if(doc == null) {
return db.close();
}
//app.error(function(err, req, res, next){
// console.error(err);
// res.send('Fail Whale, yo.');
//});
//console.dir(doc.State + " is a state!");
});
});
~~
your code looks a little chaotic, but here is what you can do.
also take a look at mongodb documentation for $set: http://docs.mongodb.org/manual/reference/operator/update/set/
var cursor = db.collection('data').find().sort(sortorder);
cursor.each(function(err, doc) {
if(err) throw err;
if(doc == null) {
return db.close();
}
// until here you code makes sense, you have a cursor,
// you checked for errors and have the current document
// now you want to update a record, you can do it like this:
var myquery = {};
myquery['_id'] = doc['_id'];
// you were missing the surrounding {}
var myupdate = { $set: { field1: "whatever value", field2: 500 } };
// obviously you want to replace field1 and field2 with your actual field names
// instead of creating a new update object and using $set
// you could also just modify the 'doc' variable and pass it again
// in the update function below instead of myupdate
db.collection('data').update(myquery, myupdate, function (err, updatedDoc) {
if (err) throw err;
console.log("successfully updated document", updatedDoc);
});
});

Resources