Getting old records from Sails Models - javascript

Im actually trying to build up a complete chat with Sails.js websockets but im facing some troubles.
I succeed to send and get new messages when a new client connect to the chat but i would new client to get the older messages (like the 20 last messages sent in the chat).
Message.js (Model)
module.exports = {
attributes: {
name : { type: 'string' },
message : { type: 'string' }
}
};
MessageController.js (Controller)
module.exports = {
new: function(req, res) {
var data = {
name: req.param('name'),
message: req.param('message'),
};
Message.create(data).exec(function created(err, message){
Message.publishCreate({id: message.id, name: message.name, message: message.message});
});
},
subscribe: function(req, res) {
Message.watch(req);
}
};
I had an idea about using the "find" function on my Model but not really conclusive.
I hope im not missing something big about Sails possibilities !
Need your help :) Thanks !

Message.find({sort: 'createdAt ASC'}).exec(function(err, results) {
//results is an array of messages
});
http://sailsjs.org/documentation/concepts/models-and-orm/query-language

I added this code to my subscribe function but i don't receive anything on my client side listening on('message')
/* Get the last 5 messages */
Message.find({sort: 'createdAt DESC'}).limit(5).exec(function(err, messages) {
for (var i = 0; i < messages.length; i++) {
sails.sockets.broadcast(req.socket, 'message', messages[i]);
}
});

Related

How to reset json file in nodejs

I need to reset a json file to an original state after a button is clicked. Currently, I am modeling with router, and I need help to extend my existing code.
This is a code snippet I wrote on server.js file, the one that I run "nodemon" to start the server.
var messages = [{index:0, rating:0}, {index:1, rating:0}]
app.get('/votes', (req, res) =>{
res.send( messages )
})
app.post('/votes', (req, res) =>{
votes.push(votes)
res.sendStatus(200)
})
so my initial state on file 'votes' (json format) is:
[{"index":0,"rating":0}, {"index":1, "rating":0}]
After some user actions, I'll add some data to this json file using this code:
<body>
// some logic here
<script>
$(() => {
$("#submit").click(()=>{
var message = [ { index:1, rating: $("#input").val()},
{ index:2, rating: $("#input2").val()}]
postMessage(message)
})
})
function postMessage(message) {
$.post('http://localhost:8080/votes', message)
}
</script>
</body>
and then I have the following in my json file
[{"index":0,"rating":0}, {"index":1, "rating":0}, {"index":1, "rating":1}, {"index":2, "rating":3}]
QUESTION: How do I reset the json file (not json variable) into the initial state with a button click for a new transaction?
I am just doing prototyping, so a quick and dirty way may work.
I'd recommand build or use some sort of user verification, and for each user have a copy of the initial data just for him. Keep in mind that this data will never garbage collected so you will have to manage deletion by yourself. I used basic IP that is given by express but that is not a good practice.
Use npm-memorystore which will give your some memory management.
If you want to identify users you can use express-session, express-jwt
var messages = [{
index: 0,
rating: 0
}, {
index: 1,
rating: 0
}];
var usersMessages = {};
app.get('/votes', (req, res) => {
var userIp = req.ip;
usersMessages[userIp] = [].concat(messages);
res.send(usersMessages[userIp]);
});
app.post('/votes', (req, res) => {
var userIp = req.ip;
var userVotes = usersMessages[userIp];
if (!userVotes)
usersMessages[userIp] = [].concat(messages);
usersMessages[userIp].push(req.body.votes);
res.sendStatus(200)
});
Take a look this:
$(() => {
let message = [];
$("#submit").click(() => {
//fill with values
message = [
{ index: 1, rating: $("#input").val() },
{ index: 2, rating: $("#input2").val() }
];
postMessage(message); //send post
message = []; //reset array
});
function postMessage(message) {
$.post("http://localhost:8080/votes", message);
}
});
Hope this helps. =D
What you need to do is, just remove all of the object from array.
You can do that as follow.
var messages = [{"index":0,"rating":0}, {"index":1, "rating":0}, {"index":1, "rating":1}, {"index":2, "rating":3}];
messages.length = 1;
console.log(messages);
Another way.
var messages = [{"index":0,"rating":0}, {"index":1, "rating":0}, {"index":1, "rating":1}, {"index":2, "rating":3}];
messages = messages.slice(0,1);
console.log(messages);
What above code do is, it will just set array back to it first value.

How to use servicebus topic sessions in azure functionapp using javascript

I have an Azure Functionapp that processes some data and pushes that data into an Azure servicebus topic.
I require sessions to be enabled on my servicebus topic subscription. I cannot seem to find a way to set the session id when using the javascript functionapp API.
Here is a modified extract from my function app:
module.exports = function (context, streamInput) {
context.bindings.outputSbMsg = [];
context.bindings.logMessage = [];
function push(response) {
let message = {
body: CrowdSourceDatum.encode(response).finish()
, customProperties: {
protoType: manifest.Type
, version: manifest.Version
, id: functionId
, rootType: manifest.RootType
}
, brokerProperties: {
SessionId: "1"
}
context.bindings.outputSbMsg.push(message);
}
.......... some magic happens here.
push(crowdSourceDatum);
context.done();
}
But the sessionId does not seem to get set at all. Any idea on how its possible to enable this?
I tested sessionid on my function, I can set the session id property of a message and view it in Service Bus explorer. Here is my sample code.
var connectionString = 'servicebus_connectionstring';
var serviceBusService = azure.createServiceBusService(connectionString);
var message = {
body: '',
customProperties:
{
messagenumber: 0
},
brokerProperties:
{
SessionId: "1"
}
};
message.body= 'This is Message #101';
serviceBusService.sendTopicMessage('testtopic', message, function(error)
{
if (error)
{
console.log(error);
}
});
Here is the test result.
Please make sure you have enabled the portioning and sessions when you created the topic and the subscription.

Specifying Mongo Query Parameters From Client Controller (MEAN.JS)

I am building an application using MongoDB, Angular, Express, and Node (MEAN stack).
I used the MEAN.JS generator to scaffold my application.
I will use the articles module as a reference.
Suppose I have 7000 records in my articles collection, and each record has a date associated with it. It is inefficient to load all 7000 records into memory every time I load the page to view the records in a table and I am seeing terrible performance losses because of it. For this reason, I would only like to load records with a date in the range of (1 Month Ago) to (1 Year From Now) and display them in the table. I can currently do this with the following:
In my articles.client.controller.js:
$scope.find = function() {
$articles = Articles.query();
};
...and in my articles.server.controller.js:
var now = new Date();
var aYearFromNow = new Date(now.getTime() + 86400000*365); //add a year
var aMonthAgo = new Date(now.getTime() - 86400000*30); //subtract roughly a month
exports.list = function(req, res) { Article.find().where('date').lt(aYearFromNow).gt(aMonthAgo).sort('-created').populate('user', 'displayName').exec(function(err, articles) {
if (err) {
return res.send(400, {
message: getErrorMessage(err)
});
} else {
res.jsonp(articles);
}
});
};
The problem is that this is not a dynamic way of doing things. In other words, I want the user to be able to specify how far back and how far forward they want to see.
How can I bind to variables (e.g. 'aYearFromNow' and 'aMonthAgo') in my client view that will change the query parameters in my server controller?
Another way is to just pass the search parameters in the query method, like this:
$scope.searchart = function() {
Articles.query({start:$scope.startDate, end:$scope.endDate}, function(articles) {
$scope.articles = articles;
});
};
and then at the server side controller, read your query string parameters like this:
exports.searcharticle = function(req, res) {
Article.find().where('date').gt(req.query['start']).lt(req.query['end']).exec(function(err, articles) {
if (err) {
res.render('error', {
status: 500
});
} else {
res.jsonp(articles);
}
});
};
This way doesn't require more routes or services.
It's probably not the cleanest way, but you can create a new service (or edit the current one to work with several parameters):
.factory('ArticlesService2', ['$resource',
function($resource) {
return $resource('articles/:param1/:param2', {
param1: '',
param2: ''
}, {
update: {
method: 'PUT'
}
});
}
]);
Then call it in your controller :
$scope.findWithParams = function() {
$scope.article = ArticlesService2.query({
param1: $scope.aYearFromNow,
param2: $scope.aMonthAgo
});
};
On the back-end, you'll need to prepare a route :
app.route('/articles/:param1/:param2')
.get(articles.listWithParams)
Add a function to your back-end controller :
exports.listWithParams = function(req, res) {
Article.find()
.where('date')
.lt(req.params.param1)
.gt(req.params.param2)
.sort('-created').populate('user', 'displayName')
.exec(function(err, articles) {
if (err) {
return res.send(400, {
message: getErrorMessage(err)
});
} else {
res.jsonp(articles);
}
});
};
Should work, haven't tested it though.

Sails.js Set model value with value from Callback

i need to provide something like an association in my Model. So I have a Model called Posts with an userid and want to get the username from this username and display it.
So my ForumPosts.js Model looks like the following:
module.exports = {
schema: true,
attributes: {
content: {
type: 'text',
required: true
},
forumTopicId: {
type: 'text',
required: true
},
userId: {
type: 'integer',
required: true
},
getUsername: function(){
User.findOne(this.userId, function foundUser(err, user) {
var username = user.username;
});
console.log(username);
return username;
}
}
};
I know that this return will not work because it is asynchronus... But how can i display it in my view? At the Moment i retrive the value with:
<%= forumPost.getUsername() %>
And for sure get an undefined return...
So the question is: How can I return this value - or is there a better solution than an instanced Model?
Thanks in advance!
Off the top of my head, you can just load associated user asynchronously before rendering:
loadUser: function(done){
var that = this;
User.findOne(this.userId, function foundUser(err, user) {
if ((err)||(!user))
return done(err);
that.user = user;
done(null);
});
}
then in your controller action:
module.exports = {
index: function(req, res) {
// Something yours…
forumPost.loadUser(function(err) {
if (err)
return res.send(err, 500);
return res.view({forumPost: forumPost});
});
}
}
and in your view:
<%= forumPost.user.username %>
This is kind of a quick and dirty way. For a more solid and long-term solution (which is still in development so far) you can check out the alpha of Sails v0.10.0 with the Associations API.
So this particularly case of associations between your models. So here you have a User model and ForumPost model and you need the user object in place of your user_id as user_id works as a relationship mapping field to your User model.
So if your are using sails V0.9.8 or below you need to handle this logic in your controller where ever you want to access User model attributes in your view.
In your controller write your logic as:
model.export = {
//your getForumPosts method
getForumPosts : function(req,res){
var filters = {};
forumPost.find(filters).done(function(err,posts){
if(err) return res.send(500,err);
// Considering only one post obj
posts = posts[0];
postByUser(posts.user_id,function(obj){
if(obj.status)
{
posts.user = obj.msg;
delete posts.user_id;
res.view({post:posts});
}
else
{
res.send(500,obj.msg);
}
});
}
}
}
function postByUser(user_id,cb){
User.findOne(user_id).done(function(err,user){
if(err) return cb({status:false, msg:err});
if(user){
cb({status:true, msg:user});
}
}
}
and then you can access your post object in your view.
Or else you can keep watch (at GitHub) on next version of sails as they have announced associations in V0.10 n it is in beta testing phase as if now.

AngularJS redirection after ng-click

I have a REST API that read/save data from a MongoDB database.
The application I use retrieves a form and create an object (a job) from it, then save it to the DB. After the form, I have a button which click event triggers the saving function of my controller, then redirects to another url.
Once I click on the button, I am said that the job has well been added to the DB but the application is jammed and the redirection is never called. However, if I reload my application, I can see that the new "job" has well been added to the DB. What's wrong with this ??? Thanks !
Here is my code:
Sample html(jade) code:
button.btn.btn-large.btn-primary(type='submit', ng:click="save()") Create
Controller of the angular module:
function myJobOfferListCtrl($scope, $location, myJobs) {
$scope.save = function() {
var newJob = new myJobs($scope.job);
newJob.$save(function(err) {
if(err)
console.log('Impossible to create new job');
else {
console.log('Ready to redirect');
$location.path('/offers');
}
});
};
}
Configuration of the angular module:
var myApp = angular.module('appProfile', ['ngResource']);
myApp.factory('myJobs',['$resource', function($resource) {
return $resource('/api/allMyPostedJobs',
{},
{
save: {
method: 'POST'
}
});
}]);
The routing in my nodejs application :
app.post('/job', pass.ensureAuthenticated, jobOffers_routes.create);
And finally the controller of my REST API:
exports.create = function(req, res) {
var user = req.user;
var job = new Job({ user: user,
title: req.body.title,
description: req.body.description,
salary: req.body.salary,
dueDate: new Date(req.body.dueDate),
category: req.body.category});
job.save(function(err) {
if(err) {
console.log(err);
res.redirect('/home');
}
else {
console.log('New job for user: ' + user.username + " has been posted."); //<--- Message displayed in the log
//res.redirect('/offers'); //<---- triggered but never render
res.send(JSON.stringify(job));
}
});
};
I finally found the solution ! The issue was somewhere 18inches behind the screen....
I modified the angular application controller like this :
$scope.save = function() {
var newJob = new myJobs($scope.job);
newJob.$save(function(job) {
if(!job) {
$log.log('Impossible to create new job');
}
else {
$window.location.href = '/offers';
}
});
};
The trick is that my REST api returned the created job as a json object, and I was dealing with it like it were an error ! So, each time I created a job object, I was returned a json object, and as it was non null, the log message was triggered and I was never redirected.
Furthermore, I now use the $window.location.href property to fully reload the page.

Categories

Resources