I am new to loopback and node.js.
I have created two models: Rating and RatingsAggregate
using the loopback explorer, I can query and post against the API just fine.
I am try to setup some basic business logic so I am editing the file Rating.js in common/models
Here is the content of it:
module.exports = function(Rating) {
Rating.afterRemote('**', function(ctx, inst, next) {
var loopback = require('loopback');
var app = loopback();
var ratingsaggregate = app.models.ratingsaggregate;
ratingsaggregate.post({"source":"foobar","restaurantID":"foobar","itemMenuName":"foobar","itemSectionName":"foobar","itemName":"foobar","nRatings1":123,"nRatings2":123,"nRatings3":123,"nRatings4":123,"nRatings5":123,"hasImage":true,"imageSize":123,"latestImageRatingID":"foobar","imageCount":123,"lastUpdated":"foobar"}, function(err, response) {
if (err) console.error(err);
next();
});
});
};
I can load my API, but whenever I run a get statement against it, I get this error:
TypeError: Cannot call method 'post' of undefined
My guess is that somehow ratingsaggregate never gets a value... but I don't know what I am doing wrong. Obviously this is not the end state of my business logic, but I am trying some basic CRUD right now between two models
And... here is the answer. There was a getModel function hidden in the documentation
module.exports = function(Rating) {
Rating.afterRemote('create', function(ctx, inst, next) {
var loopback = require('loopback');
var ratingsaggregate = loopback.getModel('ratingsaggregate');
ratingsaggregate.create({"source":"foobar","restaurantID":"foobar","itemMenuName":"foobar","itemSectionName":"foobar","itemName":"foobar","nRatings1":123,"nRatings2":123,"nRatings3":123,"nRatings4":123,"nRatings5":123,"hasImage":true,"imageSize":123,"latestImageRatingID":"foobar","imageCount":123,"lastUpdated":"foobar"}, function(err, response) {
if (err) console.error(err);
next();
});
});
};
Fixes everything and the behaviour is the expected one
Related
I have a global variable in my server side code inside a post route and i am trying to access it within another post route. The code executes perfectly when the second post route is called for the first time, but when the second post route is triggered a second time, the value of the global variable becomes undefined.
Snippet of first post route that declares the global variable:
app.post("/login", function(req, res) {
...
fs.readFile('results.json', function (err, data) {
if(err){
console.log(err)
} else{
var json = JSON.parse(data)
...
global.Identifier;
global.Identifier = Identifier;
return global.Identifier;
}
}
);
res.redirect("/");
});
snippet of second post request that accesses global variable:
app.post("/addtask", function(req, res) {
var gloablIdentifier = global.Identifier;
...
res.redirect("/");
};
(When the second post request is accessed a second time, the value of gloablIdentifier = undefined )
NOTE: I understand that using global variables is VERY BAD PRACTICE and should be avoided in most situations at all costs, but I would still like to work on this problem.
Thanks in advance
You did not wait readFile has to be finished and return response. Since, fs.readFile is async, global.Identifier will update later. You can await to read the file and then return;
app.post("/login", function(req, res) {
fs.readFile("results.json", function(err, data) {
if (err) {
console.log(err);
} else {
var json = JSON.parse(data);
global.Identifier = Identifier;
return global.Identifier;
}
// wait for read file
res.redirect("/");
});
// res.redirect("/");
});
async-await version:
const { promisify } = require("util");
const readFile = promisify(fs.readFile);
app.post("/login", async function(req, res) {
try {
const data = await readFile("results.json");
var json = JSON.parse(data);
global.Identifier = Identifier;
return res.redirect("/");
} catch (error) {
return res.redirect("/");
}
});
From the looks of it, you are using something like Express.
Even though this might be a bad practice I think that you should give a try to using the set functionality provided by express itself.
As such, in your app.js do it like this:
app.set("identifier", Identifier)
Then, in your routes:
app.post("/addtask", function(req, res) {
var gloablIdentifier = app.get('identifier')
...
res.redirect("/");
};
I did not test this, it's based on the documentation and on this answer
EDIT: I tested this and it works. Also, to change the variable again just do this on your route:
app.set('identifier', newValue)
I hope the answer is complete now!
My problem: I'm trying to HTTP.GET a random questionSchema from my database but it returns "". In my database (that is hosted in mongolab I have a few different collections, but in my questions collection I only have 3 different JSONs with 3 different questions.
I have a Schema that looks like this:
var questionSchema = new Schema({
description: String
});
module.exports = mongoose.model('Question', questionSchema);
In my routes.js I put the following:
app.get('/api/getrandomquestion', function (req, res) {
if (req.params.description) {
res.json(req.description);
} else {
res.json("");
}
});
I also have a service called QuestionService.js which is supposed to query the DB and give me back a random JSON document out of all (3) the documents that exist there. This is the code of the service:
var numberOfItemsToFind = 3;
Question.find({}, { '_id': 1}, function(err, data){
if (err) res.send(err);
var arr = shuffle.(data.slice(0));
arr.splice(numberOfItemsToFind, arr.length - numberOfItemsToFind);
var return_arr = [];
async.each(arr, function(item, callback){
Question.findById(item._id, function(err, data){
if (err) res.send(err);
return_arr.push(data);
callback();
});
}, function(err){
res.json(return_arr);
});
});
And lastly, I put these together with my questionCtrl:
controller('QuestionCtrl', function ($scope, $http, $modal) {
$http.get('/api/getrandomquestion').success(function (question) {
$scope.description = question.description;
});
});
I am using POSTMAN to make a HTTP.GET request to localhost:3000/getrandomquestion and I'm getting back just the "" as I stated.
Any help towards solving my problem (empty JSON instead of a real one) will be greatly appreciated!
The problem is in your routes.js:
app.get('/api/getrandomquestion', function (req, res) {
if (req.params.description) {
res.json(req.description);
} else {
res.json("");
}
});
req.params.description is undefined. So the if statement failed.
If param description is not necessary, You should probably define your GET API like this:
app.get('/api/getrandomquestion', function (req, res) {
QuestionService.getRandomQuestion(function(questions){
res.json(questions);
//res.send(questions);
});
});
Basically your backend receive a GET getrandomquestions API call, you just forward to fetch MongoDB using QuestionService.
express.js provides you with a decent barebone system to implement a standard MVC development pattern. However most tutorials i've seen apply controller logic in a routes file or a global app file.
In an ideal world:
Model - Manages fundamental behaviours and data
Controller - Sends commands to the model and the view
View - Renders data from the model
currently i have the following:
routes/index.js - route pointing to an action
router.get('/hotels', function(req, res, next) {
hotels.run(req, res, next);
next();
});
controllers/hotels.js - controller sending a command to a model
module.exports = {
run: function(req, res, next) {
var users = new require('../models/hotels');
users.run(function(callback) {
res.render('hotels', { title: 'Hotels page', users: callback });
});
}
}
models/hotel.js - model requesting data
module.exports = {
run: function(callback) {
connection.query(sql, function(err, rows, fields) {
callback(rows);
//console.log(rows);
});
}
}
No matter what i try, i can't get the data from the model to return to the controller to then be passed to the view. I understand there are probably multiple errors within the above code as i'm new to express. But the fundamentals should be ok, and i'm hoping it's something obvious as to why i can't return the model data,as all logic above other than the callback works.
I believe i have solved this issue, if people are looking to use a similar MVC approach on an express.js project.
routes.js - changed to match Kevin's cleaner method.
router.get('/hotels', hotels.run);
controller/hotels.js -
module.exports = {
run: function(req, res, next) {
var users = new require('../models/hotels');
users.run(function(err, callback) {
res.render('hotels', { title: 'Hotels page', users: callback });
});
}
}
models/hotel.js
module.exports = {
run: function(callback) {
connection.query(sql, function(err, rows, fields) {
callback(err, rows);
});
}
}
so now the model returns the query as requested by the controller, giving the controller the ability to pass the data to the view.
I'm wondering how to use the module node-mysql correctly in Node.js (using Express.js). I have a main router with this:
var Post = require('./models/post.js');
app.get('/archives', function (req, res) {
Post.findArchives(function(posts, err) {
if(err)
res.send('404 Not found', 404);
else
res.render('archives', { posts: posts});
});
});
And here's the content of the file post.js:
var mysql = require('mysql');
var dbURL = 'mysql://root#localhost/mydatabase';
exports.findArchives = function(callback) {
var connection = mysql.createConnection(dbURL);
connection.query('SELECT * FROM blog_posts_view WHERE status != 0 ORDER BY date DESC', function(err, rows) {
if(err) throw err
callback(rows, err);
connection.end();
});
};
How can I improve it? Improve the error handling? Also, there's the function handleDisconnect(connection); on their Github (https://github.com/felixge/node-mysql) that I'm not really sure how to integrate to make sure that the application will not crash when the database is not responding.
Thanks!
Take a look at the mysql-simple library. It combines node-mysql with a pooling library to create a connection pool, and also includes the code to handle the disconnects.
If you want to make it super easy, you could just use that module.
I'm working with Node.js, express, mongodb, and got stuck on this data passing between frontend and backend.
Note: code below is middleware code for front- and backend communication
Here I successfully get the input value from the frontend by using req.body.nr
exports.find_user_post = function(req, res) {
member = new memberModel();
member.desc = req.body.nr;
console.log(req.body.nr);
member.save(function (err) {
res.render('user.jade', );
});
};
Here is the problem, I need to use the input value I got to find the correct data from my database(mongodb in the backend) and push out to the frontend.
My data structure {desc : ''}, the desc is correspond to the input value so it should look something like this {desc: req.body.nr} which is probably incorrect code here?
exports.user = function(req, res){
memberModel.find({desc: req.body.nr}, function(err, docs){
res.render('user.jade', { members: docs });
});
};
Would love to have some help.
Thanks, in advance!
Have a look at this great tutorial from howtonode.org.
Because as you can see he uses a prototype and a function callback:
in articleprovider-mongodb.js
ArticleProvider.prototype.findAll = function(callback) {
this.getCollection(function(error, article_collection) {
if( error ) callback(error)
else {
article_collection.find().toArray(function(error, results) {
if( error ) callback(error)
else callback(null, results)
});
}
});
};
exports.ArticleProvider = ArticleProvider;
in app.js
app.get('/', function(req, res){
articleProvider.findAll( function(error,docs){
res.render('index.jade', {
locals: {
title: 'Blog',
articles:docs
}
});
})
});
Also make sure you have some error checking from the user input as well as from the anybody sending data to the node.js server.
PS: note that the node, express and mongo driver used in the tutorial are a bit older.