.toArray not workin - javascript

i have more than 20 products on the database and i am trying to display all of them so i used
Product.find({}).toArray(function(err,data){
if(err){
res.send(err)
}
if(data){
res.send(data)
}
}
but i get an error
TypeError: Product.find(...).toArray is not a function
so then i used
Product.find({},function(err,products){
if(err){
res.send(err)
}
if(products){
res.send(products)
}
})
but it only prints out 20 products. so then i tried
Product.find({},function(err,products){
if(err){
res.send(err)
}
if(products){
res.send(products)
}
}).limit(300)
but it still prints out 20 products

Use promises instead of using callbacks
Try this:
Products.find().then(products => {
res.send({ products })
}).catch(err => {
res.send({ err })
})
It should retrieve all products instead of just 20
If it retrieves just 20, check how much do you have using the .count() method

You should add options like limit before the toArray-call. Additionally I assume you have a default limit set by your included mongodb library.
This code sample should give you 300 products:
Product
.find({})
.limit(300)
.toArray(function(err,data) {
if (err) {
res.send(err);
} else if (data) {
res.send(data);
}
)};
For reference see mongodb-native #find and/or mongodb-native Cursor

Related

MongoNetworkError: connection establishment was cancelled

I'm trying to update a database using Mongoose, but I'm getting this Network error while running my node app.
const mongoose = require('mongoose')
mongoose.connect("mongodb://localhost:27017/fruitsDB")
const fruitsSchema = new mongoose.Schema({
name: {
type: String,
required: [true, "Why no Name?"]
},
rating: {
type: Number,
min: 1,
max: 10
},
review: String
});
const Fruit = mongoose.model("Fruit", fruitsSchema)
Fruit.find(function(err, fruits){
if(err){
console.log(err)
}
else{
mongoose.connection.close();
fruits.forEach(function(fruit){
console.log(fruit.name)
})
}
})
Fruit.updateOne({_id:"62b6a681eb136efde7ed17bc"}, {name: "Banana"}, function(err){
if(err){
console.log(err)
}
else{
console.log("Successfully updated the document")
}
})
Error: Commnad line error while running the node app
MongoNetworkError: connection establishment was cancelled
at connectionFailureError
at CancellationToken.<anonymous>
at Object.onceWrapper (node:events:641:28)
at CancellationToken.emit (node:events:527:28)
at ConnectionPool.close
at Server.destroy
at destroyServer
at eachAsync
It's a simple Node app created using Mongoose.
Calling the find function last worked for me. I mean, like this -
Fruit.updateOne({_id:"62b6a681eb136efde7ed17bc"}, {name: "Banana"}, function(err){
if(err){
console.log(err)
}
else{
console.log("Successfully updated the document")
}
})
Fruit.find(function(err, fruits){
if(err){
console.log(err)
}
else{
mongoose.connection.close();
fruits.forEach(function(fruit){
console.log(fruit.name)
})
}
})
Closing the connection should be at end which is the reason why the code is not getting properly executed.
I tried Calling the find function last but still getting the same error like this:
MongoNetworkError: connection establishment was cancelled
I don't know how to tackle this issue when it occurs in a running application but for now if you want to just insert the docs in collection then just comment the .find method completely and then run the application it will be inserted successfully and then comment the .updateOne method and uncomment the .find method by doing you will be successfully added the docs and could get the find result.
I did the same!
OR
I found out that for some reason .find method gets executed before .updateOne so the connection were being closed before the collection gets updated.
So, if we do this it works.
Fruit.updateOne({_id:"62b6a681eb136efde7ed17bc"}, {name: "Banana"}, function(err) {
if (err) {
console.log(err)
} else {
Fruit.find(function(err, fruits) {
if (err) {
console.log(err)
} else {
mongoose.connection.close();
fruits.forEach(function(fruit) {
console.log(fruit.name)
})
}
});
console.log("Successfully updated the document")
}
})
You can't close the connection in the find method. You are not able to interact with the db after you closed the connection. Just put mongoose.connection.close() at the end.
Just Do something like this:
`People.insertMany([man1, man2, man3],
function (err) {
if (err) {
console.log(err);
} else {
console.log("Successfully saved all
models in the database");
mongoose.connection.close();
}
});`
Closing the connection inside insertmany worked for me
After reading some solutions the TL:DR is: the mongoose.disconnect();, it's the one causing problems, the connection is being terminated before you can update anything
You should be careful while using crud methods on database. Because those methods are asynchronous.
In your case the find method executed first and closed the database connection prior to updateOne method.
Solution: You can solve that by simply changing the logic in your code like embedding find method inside updateOne method or viseversa according to your need.(By embedding we are making a way to execute them in order)
Fruit.find(function(err, fruits) {
if (err) {
console.log(err)
} else {
fruits.forEach(function(fruit) {
console.log(fruit.name)
})
Fruit.updateOne({_id:"62b6a681eb136efde7ed17bc"}, {name: "Banana"}, function(err) {
if (err) {
console.log(err)
} else {
mongoose.connection.close();
console.log("Successfully updated the document")
}
})
}
})

Mongoose find happens after res.render() is called?

i'm trying to write a "facebook clone" in nodejs with mongoDB.
The problem I'm having is every time a user goes to a user's profile he needs to get his friends array. the way i'm doing it is like this:
router.get("/user/:id/profile", isLoggedIn, (req, res) => {
let friends = [];
User.findById(req.params.id, (err, user) => {
if (err) {
req.flash("error", "There has been an error going to this persons profile.");
res.redirect("back");
} else {
if (user.friends.length > 0) {
for(var i = 0; i < user.friends.length; i++) {
User.findById(user.friends[i], (err, friend) => {
if (err) {
console.log(err);
req.flash("error", "Could not find the friends list")
res.redirect("back")
} else {
friends.unshift({
firstName: friend.firstName,
lastName: friend.lastName,
_id: friend._id
})
console.log(friends)
}
});
}
console.log(friends, "158")
res.render("user", { userData: user, friends: friends })
} else {
// render the page without the friends array.
res.render("user", { userData: user }); // im calling it userData because i have a local template variable called user and i don't want to over-write it
}
}
});
});
and what happens is that where i do the console.log(friends) inside the for loop, i get the friends array with everything correct in it, but when i do the console.log(friends) before the res.render("user") the array is empty. any idea why?
When writing code for node.js you need to get used to async functions as a LOT of addins / classes / code uses this.
Coding is not anymore "linear" but functions are called as soon as previous code is done.
In your case the findById starts a process of finding documents in mongoDB and as soon as it found them it will call the (in your case anonymous) callback function with parameters (err, friend).
Your call of res.render is outside of that callback and will be immediately called after the findById starts. That is to early.
You need to put your res.render within the callback to get the data back.
EDIT: The following code will not run properly because of the for- loop. We need to use promises as shown in Prajvals answer. Please use his second example, as that one works.
User.findById(user.friends[i], (err, friend) => {
if (err) {
console.log(err);
req.flash("error", "Could not find the friends list")
res.redirect("back")
} else {
friends.unshift({
firstName: friend.firstName,
lastName: friend.lastName,
_id: friend._id
})
console.log(friends);
res.render("user", { userData: user, friends: friends })
}
});
It is because of asynchronous nature of node. Using res.render inside your callback function or using promises will sort this out.
Without Promises
User.findById(req.params.id, (err, user) => {
if (err) {
req.flash("error", "There has been an error going to this persons profile.");
res.redirect("back");
} else {
if (user.friends.length > 0) {
for(var i = 0; i < user.friends.length; i++) {
User.findById(user.friends[i], (err, friend) => {
if (err) {
console.log(err);
req.flash("error", "Could not find the friends list")
res.redirect("back")
} else {
friends.unshift({
firstName: friend.firstName,
lastName: friend.lastName,
_id: friend._id
})
console.log(friends)
res.render("user", { userData: user, friends: friends })
}
});
}
console.log(friends, "158")
} else {
// render the page without the friends array.
res.render("user", { userData: user });
}
}
});
With Promise
User.findById(user.friends[i])
.then((friend) => {
friends.unshift({
firstName: friend.firstName,
lastName: friend.lastName,
_id: friend._id
})
})
.then(()=>{
res.render("user", { userData: user, friends: friends })
})
.catch( err=>{
console.log(err);
req.flash("error", "Could not find the friends list")
res.redirect("back")
})
----EDIT----
Now async await can also be used. I have not shown it here though.
The one which i have written without promises will not work.
For doing it with / without promise you need to use recursive way for synchronization instead of for loop.

Having issues editing an existing DB entry with Sails and Waterline

I'm using SailsJS as an API with Waterline connected to a MongoDB. I'm trying to put together an endpoint to edit existing DB entries but can't seem to get it to work and I'm hitting a wall as to why.
My route:
'post /edit/safety/:id': {
controller: 'SafetyController',
action: 'editSafety'
},
My controller function:
editSafety: function editSafety(req, res) {
var id = req.params.id;
Safety.findOneById(id).then((err, safety) => {
if (err) {
res.send(500, err);
return;
}
if (!safety) {
res.send(404, err);
return;
}
safety.title = req.body.title;
safety.description = req.body.description;
safety.status = req.body.status;
safety.save((err, updatedSafety) => {
if (err) {
re.send(500, err);
return;
}
res.send(200, updatedSafety);
});
});
},
Any push in the right direction would be greatly appreciated.
I don't recognize the Safety.findOneById method - is this something you have custom built? If not, then it is likely your problem.
Try swapping it for either:
Safety.findOne(id)
or
Safety.findOne({id: id})
Note that the returned object will be a model instance if the record exists, and undefined otherwise. If you decide to go with Safety.find instead then the returned value will be an array containing all models matching the query.
Looks like the main issue was transposing the response and err objects. It was successfully completing the query, but loading it into the err object which gets caught and a 500 error is thrown. So I changed that and simplified in a few other places.
editSafety: function editSafety(req, res) {
var id = req.params.id;
Safety.findOne(id).then((response, err) => {
var safety = response;
if (err) {
res.send(500, err);
return;
}
if (!response) {
res.send(404, err);
return;
}
safety.title = req.body.title;
safety.description = req.body.description;
safety.status = req.body.status;
Safety.update({
id: id
}, safety)
.then((result) => {
res.json(200, 'Ok!');
})
.catch((err) => {
sails.log.error('SafetyController.editSafety', err);
})
});
},

MongoDB - Mongoose: How Do I Update Simultaneously Two Separate Embedded Documents With Mongoose?

So I am trying to update the field status in my Report document and in my Station.reports sub-document which is an array of objects, in one single API call. The issue is that I am able to update the Report document, but not the station document when making the API call. After the call, the console.log(station.reports); returns the expected subdocument which is : [{"_id":"588fed278b50cd180bd6cc15","date":"2017-01-31T01:48:57.487Z","status":"Archived"}] But this is not saved in the corresponding Station document in my DB. Please I need help here. Thanks.
Station Document:
{
"_id": "588a777d4e26720e7afa7e1e",
"phone": "(007) – 007 – 7007",
"name": "name1",
"email": "name1#email.com",
"reports": [
{
"status": "Submitted",
"date": "2014-01-31T01:48:57.487Z",
"_id": "588fed278b50cd180bd6cc15"
}
]
}
Report Document
{
"_id": "588fed278b50cd180bd6cc15",
"description": "Description of the report",
"time": "05:48 PM",
"date": "2017-01-31T01:48:57.487Z",
"status": "Archived",
"location" : "123 Main Street"
"station" : "588a777d4e26720e7afa7e1e"
}
API Call
router.put('/reports/:id/updateStatus', function (req, res) {
Report.findById(req.params.id, function(err,report){
// if there is an error retrieving, send the error.
// nothing after res.send(err) will execute
if (err)
return res.send(err);
// Update the Report object
report.status = req.body.status;
// Update the Corresponding station.reports subdocument
Station.findOne({_id:report.station}, function (err, data) {
if(err) return console.log(err);
data.reports.forEach(function(rpt){
if (rpt._id == req.params.id){
rpt.status = req.body.status
data.save(function (err, station) {
if (err)
return res.send(err);
console.log(station.reports);
})
}
})
})
report.save(function (err, report) {
if (err)
return res.send(err);
res.json(report);
})
});
})
You are doing mistake while updating the station object. Use findOneAndUpdate to find the matching Station document, and then change the status of the matched reports item(matched using reports._id).
Try this:
Station.findOneAndUpdate({
_id:report.station,"reports._id":req.params.id
},{
$set : {reports.$.status : req.body.status}
},function(err){
if(err)
return res.send(err);
});
report._id will find the array element whose _id is req.params.id and report.$.status will update only the matching element of the array.
For more information on positional $(update) operator, Read mongoDB positional Documentation.
Also, i would suggest to save the report object in the callback of update. As nodejs is asynchronous, it will not wait for the update to finish, if you are saving report outside of the callback. And, you might get Cant set the headers after they are sent error. Thus, its recommended to do it in the callback.
Thus your final API code would look like:
router.put('/reports/:id/updateStatus', function (req, res) {
Report.findById(req.params.id, function(err,report){
// if there is an error retrieving, send the error.
// nothing after res.send(err) will execute
if (err)
return res.send(err);
// Update the Report object
report.status = req.body.status;
// Update the Corresponding station.reports subdocument
Station.findOneAndUpdate({
"_id":report.station,"reports._id":req.params.id
},{
$set : {"reports.$.status" : req.body.status}
},function(err, result){
if(err)
return res.send(err);
console.log(result);
report.save(function (err, report) {
if (err)
return res.send(err);
res.json(report);
});
});
});
})
UPDATE
Alternate Method
Another way can be, You can proceed in the original way, but don't save the data inside the forEach, instead save the data sheet forEach finishes.
Station.findOne({_id:report.station}, function (err, data) {
if(err) return console.log(err);
data.reports.forEach(function(rpt){
if (rpt._id == req.params.id){
rpt.status = req.body.status
}
});
data.save(function (err, station) {
if (err)
return res.send(err);
console.log(station.reports);
report.save(function (err, report) {
if (err)
return res.send(err);
res.json(report);
});
})
})
Hope this helps!
After multiple attempts, and with the help of Ravi, I was able to figure out a solution that worked for me pretty well. The only thing that changed was my API call. The rest of the code was unchanged.
Hope this helps someone having similar needs.
API CALL
router.put('/reports/:id/updateStatus', function (req, res) {
Report.findById(req.params.id, function(err,report){
// if there is an error retrieving, send the error.
// nothing after res.send(err) will execute
if (err)
return res.send(err);
// Update the Report object
report.status = req.body.status;
// Update the Corresponding station.reports subdocument
Station.findOne({_id:report.station}, function (err, info) {
if(err) return console.log(err);
info.reports.forEach(function(rpt){
if (rpt._id == req.params.id){
Station.update({_id:info._id, "reports._id":rpt._id },
{
$set:{"reports.$.status": req.body.status }
},function (err, results) {
if(err) return console.log("This Station couldn't be updated " + err);
console.log(results)
}
)
}
})
report.save(function (err, report) {
if (err)
return res.send(err);
res.json({report:report, station:info});
});
})
});
})

Node.js - print result from sql

I am trying to run a select query from db and print results. But even i see result in console i don't see in index page. (Hovewer i see result in console but it is also doesn't show correctly. I have 2 rows in db but i see 3 lines for each row. So result in console is : 2X3=6 rows.) I put screenshot about console result end of the question.
Code in app.js
app.use('/', routes, function(req, res){
pg.connect(connect, function(err, client, done){
if(err){
return console.error('errrr', err)
}
client.query('select * from recipes', function(err, result){
if(err){
return console.error('error running query', err);
}
console.log(result.rows);
res.render('index.njk', { recipes: result.rows});
done();
});
});
});
Code in index.njk
<ul>
{% for name, item in recipes %}
<li>{{ name }}: {{ item.name }}</li>
{% endfor %}
</ul>
this is result of the console
Can you please help me to fix it?
It seems like (via your picture of the console) that result.rows is an array of arrays that has 2 values in it. Therefore, while looping over the value in your index.njk, recipes is an array of arrays and doesn't contain an item that has a name attribute.
If you set recipes: result.rows[0] that should provide a quick fix:
res.render('index.njk', { recipes: result.rows[0]});
This allows you to get the first element in your array of arrays, which is okay, because the array held within only has 1 element (the 2 items you actually want!). You should check before you do this that result.rows.length > 0 so you don't go out of bounds and get an error.
if(result.rows.length > 0) {
res.render('index.njk', { recipes: result.rows[0]});
}else {
console.log('No rows found in DB');
}
I have solved my issue by using below code block in index.js instead of using app.js. I am not sure it is correct way but it is working fine now. If it is not correct way, let me correct it please.
router.get('/', function(req, res){
pg.connect(connect, function(err, client, done){
if(err){
return console.error('errrr', err)
}
client.query('select * from recipes', function(err, result){
if(err){
return console.error('error running query', err);
}
if(result.rows.length > 0) {
res.render('index.njk', { recordResult: result.rows});
console.log(result.rows);
}else {
console.log('No rows found in DB');
}
done()
});
});
});

Categories