I'm following a simple tutorial.
Thing is, I'm using momngoose instead of Mongo.
I had no problems until I get to this point:
app.get('/', (req, res) => {
db.collection('quotes').find().toArray((err, result) => {
if (err) return console.log(err)
// renders index.ejs
res.render('index.ejs', {quotes: result})
})
})
With this, the quotes can be accessed and manipulates on index.ejs
now, I tried doing this:
app.get('/theroute', (req, res) => {
MyMongoModel.find()
.then(documents => {
res.render('index.ejs', *not entirely sure on what to put here*)
})
});
but when I tried to use the documents on the index.ejs page, I got a "not defined" result.
And that's it. No sure on how to google this or what should I do.
Thanks!
Try the following:
MyMongoModel.find({}, (err, foundQuotes) => {
if(err) return console.log(err);
res.render('index.ejs', {quotes: foundQuotes});
}
The first argument passed into find(), the {}, will retrieve all database entries matching the particular model, and passes that collection into the callback function (find()'s second argument), as foundQuotes.
In the callback function, index.ejs is rendered (if there are no errors) and foundQuotes is assigned to a variable called quotes. quotes will then be accessible in your index.ejs file.
Related
I have tried several methods to delete my photo, especially using fs.unlink but it seems not working at all, you can see from picture below that i save my photos in assets->img->products
and so my database looks like this
and my code looks like this
router.get("/admin/products/:id/delete", (req, res) => {
Product.findByIdAndRemove(req.params.id, (err, photo) => {
if (err) {
req.flash("error", "deleting photo failed");
return res.render("/admin/products/");
}
fs.unlink(photo.image1, function() {
console.log(photo.image1);
return res.redirect("/admin/products");
});
});
});
what is wrong from my code that did not delete my photo from my file?
It can not delete photos because you are passing the relative path as the first parameter.
photo.image1 = assets/img/products/image1.jpg
Try passing the passing the absolute path( from the root directory of your machine).
fs.unlink("absolute-path-to-assetsParentFolder" + photo.image1, function() {
console.log(photo.image1);
return res.redirect("/admin/products");
});
I have the following basic document in mongo:
connecting to: test
> db.car.find();
{ "_id" : ObjectId("5657c6acf4175001ccfd0ea8"), "make" : "VW" }
I am using express, mongodb native client (not mongoose) and ejs.
collection.find().toArray(function (err, result) {
if (err) {
console.log(err);
} else if (result.length) {
console.log('Found:', result);
mk = result;
console.log('mk = ', mk);
} else {
console.log('No document(s) found with defined "find" criteria!');
}
//Close connection
db.close();
});
}
});
Here is the render code:
// index page
app.get('/', function(req, res) {
res.render('pages/index', { make: result });
});
And i want to pass the data make: VW into my index.ejs file:
<h2>Cars:</h2>
<h3>My favorite make is <%= make %>
This should be real simple and straightforward but i just don't understand how to pass the "mk" variable (which i can console.log to the screen) to be rendered by the ejs view?
You should use the find method inside the route (or with a callback) to get the result and render it:
app.get('/', function(req, res) {
collection.find().toArray(function(err, result) {
if(err) {
console.log(err);
res.status('400').send({error: err});
} else if(result.length) {
console.log('Found:', result);
mk = result;
console.log('mk = ', mk);
res.render('pages/index', {make: mk});
} else {
console.log('No document(s) found with defined "find" criteria!');
res.status('400').send({error: 'No document(s) found'});
}
//Close connection
db.close();
});
});
Very simple, your are outputting an array of JSON objects
Here is one way to visualise it:
[{a:b},{a:b},{a:b},{a:b}];
If you want the first result it would be array[0].a
so you simply need to call it this way:
<%= make[0].(your database key here) =>
//example
<%= make[0].name =>
A more sensible way to get this done would be to iterate through the array and output only the result you want on the server side. If you send all your data to your client you might have security issues depending on what you send.
It should be simple, but you are defining mk just like this: mk = result So because you want to pass a variable to an ejs file you need
"var mk = result"
Have a good day, Ben.
I'm using a generic rest api that allow passing the mongo collection name on the request and serve it's content.
My LIST command looks like that:
router.get('/:collectionName', function(req, res, next) {
req.collection.find().sort('-created_on').exec(function(e, results){
if (e) return next(e);
res.send(results)
});
});
It works great.
My problem is that I want every list query to populate sub objects if exists.
I tried:
req.collection.find().populate().sort..
But obviously I get an error:
TypeError: utils.populate: invalid path. Expected string. Got typeof undefined
Help?
In the end I had to patch it:
router.get('/:collectionName', function(req, res, next) {
var populationQuery = [];
var paths = req.collection.schema.paths;
for (var path in paths) {
if (paths[path].caster) {
populationQuery.push({path: path});
}
}
req.collection.find().populate(populationQuery).sort('-created_on').exec(function (e, results) {
if (e) return next(e);
console.log(results);
res.send(results)
});
});
This works, but I guess there should be some better solution
I am coding a basic project manager, nothing fancy. I am writing the page where the project is created (with AngularJS) and am sending all the $scope to /create (the backend is Express.js). The router gets the JSON perfectly, and save it to a local MongoDB without problems.
My problem is that I want to set a message telling that the project was created successfully and send it back to AngularJS. This is my code.
router.js
module.exports = function(app, db) {
app.post('/create', function (req, res) {
var create = require("./../scripts/create")(req, res, db);
console.log(create); //just for testing whether I can receive the message.
});
}
create.js
module.exports = function(req, res, db) {
db.collection('projects').insert(req.body.project, function(err, docs) {
if (err) throw err;
return 'Project created.'; //I want to return this string.
});
};
I don't know how to return something from inside the db.collection.insert's callback function.
So you have to remember that anonymous function calls in JavaScript are not assigned to anywhere. They are passed, and then lost. This is usually why we don't really have return statements in them.
var x = function () { return y }; gives x the value of y but since there is never an assignment of the value of a callback, a return statement is meaningless. Callbacks, no matter if they have a return value, will not give you a value. They may feed that return value up to the function that they were given to, but they are entirely lost to you.
The way to get around this is to do some trickery with the scope. Basically what you want to do is 'bump' the value you want to return up a scope you can assign and then return it there. For example, you can do this:
module.exports = function(req, res, db) {
var stringToReturn;
db.collection('projects').insert(req.body.project, function(err, docs) {
if (err) throw err;
stringToReturn = 'Project created.'; //I want to return this string.
});
return stringToReturn;
};
This will work because the return value gets bound to module.exports, which is in turn bound to the result of
var create = require('./create');
console.log(create('something')) //should log 'Project created.'
Solved!!
Router.js
module.exports = function(app, db) {
app.post('/create', function(req, res) {
var create = require("./../scripts/create")(req, res, db);
});
});
Create.js
module.exports = function(req, res, db) {
db.collection('projects').insert(req.body.project, function(err, records) {
if (err) throw err;
res.send("Project created.");
});
};
Now Angular is receiving the response from the server.
I am using express and mongoose to list cats in my home page
app.get('/', function(req, res) {
Model.cats.find(function(err, ret) {
res.render('home.jade', {cats: ret});
})
});
Now lets say I wanted to display cats and dogs as well. How could I do it? The find function is async after all, so Im not sure how to prepare the response.
If you include the async npm module, it's quite simple:
app.get('/', function(req, res) {
async.parallel({
cats: function(callback) {
Model.cats.find(function(err, ret) {
callback(null, ret);
});
},
dogs: function(callback) {
Model.dogs.find(function(err, ret) {
callback(null, ret);
});
}
},
function(err, results) {
// results will be { cats: results, dogs: results}
res.render('home.jade', results);
});
});
The technique above starts two named async requests, one cat and the other dog. Each function calls your Models. When complete, they call the callback passing any errors (which I've just put as null above) and the results of the find. It's quite handy when using named calls this way as the results will be placed in two properties of a single object which you could pass directly to the render method.