I am trying to fetch data from mongodb's collection. My code is executing only single row data in json format. But when I console log my data I can see all the row data.
const mongoose = require('mongoose');
const AllMinisters = require('../models/allMinisters');
var db;
var mongodb = require("mongodb");
// Initialize connection once
mongoose.connect("******", { useNewUrlParser: true }, function(err, database) {
if(err) return console.error(err);
db = database;
// the Mongo driver recommends starting the server here because most apps *should* fail to start if they have no DB. If yours is the exception, move the server startup elsewhere.
});
exports.getAllMinisters = (req,res,next)=>{
db.collection("users").find({}, function(err, docs) {
if(err) return next(err);
docs.each(function(err, doc) {
if(doc) {
console.log(doc);
var response = {
statusCode: 200,
headers: { 'Content-Type': 'application/json' },
body: doc
}
res.end(JSON.stringify(response));
}
});
});
};
This output in JSON as
However the console report shows all
How can I show all row data in JSON
You have docs.each in your code that will iterate over all the doc you get from the find() query (which is an array) and inside that each block you are sending the response i.e, res.end(JSON.stringify(response));, which executes immediately for the first record and hence you get a single object as a response instead of array.
To return the array you need to put res.end(JSON.stringify(response)); outside the each() loop with toArray function. You can even remove the each() loop if that is not required. So, your code will be something like:
exports.getAllMinisters = (req, res, next)=>{
db.collection('users').find({}).toArray(function (err, docs) {
if (err) {return next(err);}
docs.each(function (err, doc) {
if (doc) {
//code for single doc
console.log(doc);
}
});
res.statusCode = 200;
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify(docs));
});
};
Related
I am using Typescript, Express, PostgresDB.
Here is my code for connecting to the database cluster.
import { Pool } from "pg";
const myPool = new Pool({
host: `${process.env.DATABASE_URL}`, //somedb.abc.us-east-1.rds.amazonaws.com
database: `${process.env.DATABASE_NAME}`, //dbName
user: `${process.env.DATABASE_USER}`, //dbUser
password: `${process.env.DATABASE_PASSWORD}`, //dbPassword
port: 5432
});
myPool.connect();
Here is my post route:
const router = express.Router();
router.post("/item/new", async (request, response) =>{
try{
const { itemTitle } = request.body;
const myItem = await myPool.query(`INSERT INTO items VALUES('${itemTitle}')`), (resp, err) =>{
if(err){
return err;
}
return resp;
});
return response.status(201).json({message: myItem});
}catch(err){
return response.status(400).json({message: `${err}`});
}
});
When I send the request, I get the following response with a 201 status code, but nothing
is inserted into the database:
{
"message": {}
}
It's because you're sending the callback function with the wrong argument's order. The first argument for the callback is error, not result.
It should be like this:
client.query('SELECT NOW() as now', (error, result) => {
if (error) {
console.log(error.stack)
} else {
console.log(result.rows[0])
}
})
documentation.
You can try to print the query that you are passing to find the error.
The reason is that you are concatenating a json object with string which is wrong, instead try this:
`INSERT INTO items(col1, col2) VALUES(${itemTitle.col1}, ${itemTitle.col2})`
The existing code was written as MySQL query and I am now working on converting it to Mongoose query.
I need to get five data sorted by the most recent subscription year from the main page.
The existing code brought this result value into an array. And data was delivered through pug view, and Mongoose seems to bring the result value of Object. In this case, I wonder how to deliver the data through Pug view.
I checked importing data from the terminal to the console.log, but an error called 'Error [ERR_HTTP_HEADERS_SENT]: Cannot set heads after they are sent to the client occurs and no data is passed to the pug. I wonder why this problem occurs.
[MySQL Query]
router.get("/", function (req, res, next) {
// Main page Profile Data Process
db.query(`SELECT * FROM user ORDER BY registerDate DESC LIMIT 5`, function (
error,
data
) {
// Log Error
if (error) {
console.log(error);
}
res.render("main", {
dataarray: data,
_user: req.user,
url: url
});
});
});
[Mongoose Query]
router.get("/", function (req, res, next) {
let dataarray = [];
let userData = db.collection("user").find().limit(5).sort({
"created_at": -1
});
userData.each(function (err, doc) {
if (err) {
console.log(err);
} else {
if (doc != null) {
dataarray.push(doc)
}
}
// console.log(dataarray.login)
console.log(dataarray);
res.render("main", {
dataarray,
_user: req.user
})
});
});
[pug file]
each profile in dataarray
.col-lg-4
img.rounded-circle(src=`${profile.avatar_url}` alt='Generic placeholder image' width='140' height='140')
h2=`${profile.login}`
p=`${profile.bio}`
p
a.btn.btn-secondary(href=`/${profile.login}` role='button') View details »
You are sending the request in multiple chunks, node/express uses one request and one response.
Cannot set heads after they are sent to the client
Is the error that happens when the res.render is called the second time. At this point, the one request has already left the node/express process and this is tell you that you're trying to violate the one request/one response paradigm.
This is the part of your code where you can see why this happens.
router.get("/", function (req, res, next) {
let dataarray = [];
let userData = db.collection("user").find().limit(5).sort({
"created_at": -1
});
userData.each(function (err, doc) {
This part of your code will try to send a response for each item in your resultset.
Something like this will work properly (I didn't test it):
router.get("/", function (req, res, next) {
db.collection("user").find().limit(5).sort({ "created_at": -1 }, function(err, userData){
res.render("main", {
dataarray: userData,
_user: req.user
})
});
});
In other words, only one res.render is required and pass the entire result set into that.
I'm using Node.js/Express.js to install data to my MySQL DB.
Inserting data works fine, but returning success / fail gives me an error.
TypeError: Cannot read property 'status' of undefined
This is my code:
var crud = {
newProject: function (req, res, callback) {
db.query('INSERT INTO projects SET ?', req.body, function(err, res) {
// This is where it fails
if(err){
return res.status(500).json({error: err});
} else {
return res.status(200).json({success: 'Insert row success'});
}
});
},
}
// Express routing
app.post('/project/*', crud.newProject);
What am I not getting right here?
Solution
So this is what I used to make it work (after changing 'res' to 'resp' as suggested):
if (err) throw err;
res.end(JSON.stringify({response: 'Success'}));
Your defining res twice. The express response object is getting overwritten by the data param in your node callback.
Try the following (see comment)
var crud = {
newProject: function (req, res, callback) {
// changed 'res' to 'resp' to avoid collision with Express' 'res' object
db.query('INSERT INTO projects SET ?', req.body, function(err, resp) { // here's your error
// This is where it fails
if(err){
return res.status(500).json({error: err});
} else {
return res.status(200).json({success: 'Insert row success'});
}
});
},
}
// Express routing
app.post('/project/*', crud.newProject);
If you define error-handling middleware functions after the last app.use() in your main configuration
app.use(function (err, req, res, next) {
res.status(500).send(err.message || 'Internal server error.')
})
You can use the next callback as a catchall error handler, so the above would then become
var crud = {
newProject: function (req, res, callback) {
db.query('INSERT INTO projects SET ?', req.body, function(err, resp) {
if (err) return callback(err);
return res.json({success: 'Insert row success'});
});
},
}
// Express routing
app.post('/project/*', crud.newProject);
res.json() by default should add a 200 Success code to the response header. Ideally you would want to inspect the resp data param from the node callback after checking the state of err to properly handle the response and proceed accordingly, especially if you are dealing with last evaluated records associated with a continuation token usually provided in the response which some DBALs and APIs do for you and some don't. Either way you will want to be sure additional recursion isn't necessary to fetch remaining records before responding successfully.
Looks like the res object is undefined as it is not returning any response after the insert. You may return a new object like:
return {
status: 200,
json: {success: 'Insert row success'}
}
The code is set up this way:
var express = require('express');
var router = express.Router();
var mongo = require('mongodb').MongoClient;
function getData(){
db.collection("collection_name").find({}).toArray(function (err, docs) {
if (err) throw err;
//doing stuff here
}
var dataset = [
{//doing more stuff here
}
];
});
}
router.get("/renderChart", function(req, res) {
mongo.connect(url_monitor, function (err, db) {
assert.equal(null, err);
getData(res);
});
});
When I run the code and trying to get to /renderChart when running, I get the "ReferenceError: db is not defined". I came across a similar case, and think it may be a similar problem caused because mongodb.connect() is called asynchronously, but I couldn't get it to work:
Express js,mongodb: "ReferenceError: db is not defined" when db is mentioned outside post function
The problem here is you don't pass the db to the function, so it's undefined.
A solution:
function getData(db, res){
db.collection("collection_name").find({}).toArray(function (err, docs) {
if (err) throw err;
//doing stuff here
}
var dataset = [
{//doing more stuff here
}
];
});
}
router.get("/renderChart", function(req, res) {
mongo.connect(url_monitor, function (err, db) {
assert.equal(null, err);
getData(db, res);
});
});
You'll probably need to pass the req at some point too, or make specific db queries. And you'll probably want to use promises or async/await to better deal with all asynchronous calls.
Its Simple Javascript.
You are using a variable db in your file, which is not defined, so it will throw an error.
You need to do something like this .
var findDocuments = function(db, callback) {
// Get the documents collection
var collection = db.collection('documents');
// Find some documents
collection.find({}).toArray(function(err, docs) {
assert.equal(err, null);
assert.equal(2, docs.length);
console.log("Found the following records");
console.dir(docs);
callback(docs);
});
}
I have the same problem before, instead of passing db to routing function, My solution is to make db variable global like
var mongojs = require('mongojs')
global.db = mongojs(<mongodb url>);
then db variable can be used in any part of your code
If you're using express, put that in your app.js file and you will never have to worry about db variable anyore.
PS: some people think that using global is not a good practices, but I argue that since global is a node.js features and especially since it works, why not
node.js global variables?
You don't have tell the codes, that which database you want to use.
how to get databases list https://stackoverflow.com/a/71895254/17576982
here is the sample code to find the movie with name 'Back to the Future' in database sample_mflix > collection movies:
const { MongoClient } = require("mongodb");
// Replace the uri string with your MongoDB deployment's connection string.
const uri =
"mongodb+srv://<user>:<password>#<cluster-url>?retryWrites=true&writeConcern=majority";
const client = new MongoClient(uri);
async function run() {
try {
await client.connect();
const database = client.db('sample_mflix');
const movies = database.collection('movies');
// Query for a movie that has the title 'Back to the Future'
const query = { title: 'Back to the Future' };
const movie = await movies.findOne(query);
console.log(movie);
} finally {
// Ensures that the client will close when you finish/error
await client.close();
}
}
run().catch(console.dir);
to get list of database, put await client.db().admin().listDatabases() on fun function. e.g.
async function run() {
try {
await client.connect();
var databasesList = await client.db().admin().listDatabases();
console.log("Databases:");
databasesList.databases.forEach(db => console.log(` - ${db.name}`));
learn MongoDB more from official docs: https://www.mongodb.com/docs
I seem to be having issues performing HTTP Put requests inside an array in AngularJS and ExpressJS. The issue is, when I call the HTTP Put the first time, everything works correctly. However, when I try to call a second time, it doesn't work. The following is my attempt:
When I click a button, I call perform the following HTTP Put Request:
$scope.currentUser.eventsAttending.push(event.eventName);
$http.put('/api/users/' + $scope.currentUser._id, $scope.currentUser)
.success(function(data){
console.log("Success. User " + $scope.currentUser.name);
});
Here is my User schema/model in User.model.js:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var User = require('./user.model');
var UserSchema = new Schema({
name: String,
...
eventsAttending: [{ type: String, ref: 'Event'}]
});
I route the HTTP Put Request as so in index.js:
router.put('/:id', controller.update);
And here is my actual HTTP Put function called controller.update in User.controller.js:
// Updates an existing event in the DB.
exports.update = function(req, res) {
if(req.body._id) { delete req.body._id; }
User.findById(req.params.id, function (err, user) {
if (err) { return handleError(err); }
if(!user) { return res.send(404); }
var updated = _.merge(user, req.body);
updated.markModified('eventsAttending');
updated.save(function (err) {
if (err) { return handleError(err);}
return res.json(200, user);
});
});
};
...
function handleError(res, err) {
console.log("Error: ", err);
return res.send(500, err);
}
On the second time where I try to call the HTTP Put function (exports.update above), I always get an error in Mongoose that says:
TypeError: Object VersionError: No matching document found. has no method 'send'
at handleError (/Users/schan/test/go-v2/server/api/user/user.controller.js:131:14)
at Promise.<anonymous> (/Users/schan/test/go-v2/server/api/user/user.controller.js:43:25)
The error is basically where I call the if(err) return { handleError(err); } in the HTTP Put function and when I print out the error, I get Error undefined. I'm honestly unsure on how to debug this or what I may be doing wrong. Can anyone point me in the right direction? If so that would be great! Thanks.
You're not passing res to handleError(). Change instances of handleError(err); to handleError(res, err);