How to use queries in a loop with sails.js async structure? - performance

I'm new to MVC programming and also to Sails.Js, and I'm sure I'm not using it the right way.
What I want to do is to ask my database some informations, create an array with that and then return the data to the view.
Here is what I do:
model.exports = {
'parse': function(req, res) {
var week = [0,0,0,0,0,0,0];
Elements.find({ date : {'>=' : start_date, '<' : end_date }}).exec(function countCB(error, found) {
while (found.length){
week[found.date]++;
total++;
found.pop();
};
res.view('static/emissions', { data : week });
});
};
};
Here is how Id' like to do, but the async structure of Node make it fail:
model.exports = {
'parse': function(req, res) {
var week = [0,0,0,0,0,0,0];
for (var day = 0; day < 7; day++){
Elements.count({ date : {'>=' : start_date + day, '<' : end_date + day }}).exec(function countCB(error, count) {
week[day] = count;
});
};
res.view('static/emissions', { data : week });
};
};
So am I doing it rigth with the first method ? If no, could you please give me an example that show how to do it correctly ?
Thanks :)

Finally I managed to do what I wanted using the mongodb aggregate native method.

Related

ASP.NET Ajax Get Takes too long time

I have an asp.net mvc project. I am getting some questions and answers for questions from database by ajax get. My query takes too long. How can i edit my code to work faster?
I am storing my questions and answers seperate tables. Each answer is related questions by ids.
Thanks for answers.
My view:
$.ajax({//GET QUESTIONS
url: '#Url.Action("GetQuestionsBySubCategory", "Order")',
type: "GET",
data: { subcattext : selectedSubCategory },
success: function (result) {
$('<div class=\"form-group\" id=\"sorularform\" ><input name=\"altcat\" value=\"' + selectedSubCategory + '\" type=\"hidden\">').prependTo("#sorular");
// loop each question
for (var i = 0; i < result.length; i++) {
//IF QUESTION 1 START
if (result[i].QuestionType == 1) {
$('<label for=\"exampleFormControlSelect' + i + '\" > ' + result[i].Description + '</label ><select name=\"' + result[i].Description + ' \" class=\"form-control\" id=\"exampleFormControlSelect' + result[i].Id + '\"></select>').appendTo("#sorularform");
var questionid;
$.ajax({//GET ANSWERS
url: '#Url.Action("GetAnswersByQuestionId", "Order")',
type: "GET",
data: { questionid: result[i].Id },
success: function (answerresult) {
for (var a = 0; a < answerresult.length; a++) {
$('<option>' + answerresult[a].Description + '</option>').prependTo("#exampleFormControlSelect" + answerresult[a].Question_Id);
}
},
error: function (err) {
// the call thrown an error
console.log("Hata Oluştu")
},
complete: function () {
//$(".loading").hide();
}
});
};
}
},
error: function (err) {
// the call thrown an error
console.log("Hata Oluştu")
},
complete: function () {
//$(".loading").hide();
$("</div>").appendTo(".form-group");
$('#yersec').insertBefore('#sorularform');
//$('#sorular').html(table);
}
});
Controller.cs
public ActionResult GetQuestionsBySubCategory(string subcattext)
{
var subcatid = subCategoryServices.GetAll().Where(x => x.Title == subcattext).FirstOrDefault().Id;
IEnumerable<QuestionVM> questionList = questionServices.GetAll().Where(x => x.SubCategory_Id == subcatid);
return Json(questionList, JsonRequestBehavior.AllowGet);
}
[HttpGet]
public ActionResult GetAnswersByQuestionId(int questionid)
{
IEnumerable<AnswerVM> answerList = answerServices.GetAll().Where(x => x.Question_Id == questionid);
return Json(answerList, JsonRequestBehavior.AllowGet);
}
If you want to make your querying faster, I would recommend Dapper. Dapper is a lightweight ORM that runs almost as fast as native SQL. There is a good tutorial that I would recommend you reading here: https://www.c-sharpcorner.com/article/asp-net-mvc-crud-with-dapper-micro-orm/
Essentially, you'll be running queries like this (this isn't exact but it's very close to the Dapper syntax without seeing your database structure or the rest of your code):
public ActionResult GetQuestionsBySubCategory(string subcattext)
{
var subcatid = db.Query("SELECT Id from SubcategoryServices WHERE Title = #title", new { title = subcattext });
IEnumerable<QuestionVM> questionList = db.Query("SELECT * FROM QuestionServices WHERE SubCategory_Id = #subcategoryId", new { subcategoryId = subcatid });
return Json(questionList, JsonRequestBehavior.AllowGet);
}
Aside - your DOM manipulation is very slow too, so that could also be making your application slower too. The technical reason is because the DOM has to re-render itself once you append elements to it. Rendering takes time.
It is out of the scope to create your whole application here, but I would strongly recommend at ReactJs or Vue as front-end libraries to create faster frontend code.

Recursive Query to get more than 1000 results outside Parse.cloud impossible?

I'm in need to fetch over 1000 elements from a Class.
So I tried following advices on this topic, but something is not working correctly, and already spent the whole day to find a solution.
Parse.Cloud.define("getFollow", function(request, response) {
var following = [];
var user = request.params.user;
user.fetch().then(function(result) {
if (!result.get('following')) {
following = getFollowing({
'user': user
});
}
}).then(function() {
response.success(following);
}, function(error) {
response.error(error);
});
});
function getFollowing(request) {
var count = 0;
var skip = request.skip || 0;
var limit = 1000;
var following = request.following || [];
var Follow = Parse.Object.extend('follow');
var query = new Parse.Query(Follow);
query.limit(limit);
query.ascending('objectId');
query.skip(skip * limit);
query.equalTo('followers', request.user);
query.find().then(function(results) {
skip+= 1;
count = results.length;
/* I can't see any DEBUG, seems nothing is queried */
console.log('[DEBUG] Check <count>: ' + count);
return Parse.Promise.when(results.map(function(result) {
following.push(result.get('followed'));
}));
}).then(function() {
if(count >= limit) {
following = getFollowingUsers({
'user': request.user,
'skip': skip,
'following': following
});
}
}).then(function() {
return following;
}, function(error) {
return error;
});
}
I tried many variant of this code, trying to return the very first result of the query, rather than a collection. I also tried to remove all contraints, but even so, my query seems not to be run.
I also tried to use a Cloud.code function to make this recursively using only Parse.Cloud, but if I do that, I'm having a message Too many recursive calls into Cloud Code
What did I do wrong with this logic ?

Not in query with Parse.com API

Given the Objects:
_User: (id, name, etc)
Trip: (id, _user, startDate, endDate, notes)
Is it possible to use the Parse Javascript API to find users who don't have any trips? In SQL it would be:
SELECT * FROM _User WHERE id NOT IN (SELECT _User FROM Trips)
Is that possible in Parse without selecting all users and then checking whether each one has trips?
Perhaps the question is better expressed in code:
var Trip = Parse.Object.extend("Trip");
var innerQuery = new Parse.Query(Trip);
var query = new Parse.Query(Parse.User);
query.doesNotMatchQuery("???", innerQuery);
query.find({
success: function(users) {
users.forEach(function(u){
console.log(u.get('name'));
});
}
});
What should go in the ??? User, _User and id return all Users, not those where there are no Trips.
In the end I used promises for this and can find no way to do it 'out of the box'. It's almost certainly best to wrap this up into cloud code.
Here's some sample code:
// Setup outer query
var query = new Parse.Query("Trip");
query.include('nomad');
query.find().then(function(tripsStartingNextWeek) {
var promises = [];
tripsStartingNextWeek.forEach(function(t){
promises.push((function(t){
var promise = new Parse.Promise();
var toNomad = t.get('nomad');
// inner query
var myFutureTrips = new Parse.Query("Trip");
myFutureTrips.notEqualTo('deleted', true);
myFutureTrips.find().then(function(futureTrips) {
// these records match both queries
if (futureTrips.length > 0) {
// do something
} else {
// do something else
}
promise.resolve();
});
return promise;
})(t));
});
return Parse.Promise.when(promises);
})
.then(function() {
status.success("Last trip job finished");
});

Kendo Datetimepicker How to prevent change event?

I am using a kendo datetimepicker. When user opens the calender and select any date I need to check for some other dates, ie need to run validations if the date is wrong then prevent the new date from filling the date picker and keep the old value, otherwise allow datepicker to change value. I tried with event.preventDeafult , but unfortunatly it is not working..
Is there any way to acheceive this?
Here is the fiddle enter link description here
Any help is appreciated.
Example fiddle here
$("#datePicker").kendoDatePicker({
change:function(event){ alert(1);
// some validations here
event.preventDeafult(); }
});
Go through this answer. May any lines help you to solve your problem. You can simply assign like this.
$("#datepicker").kendoDatePicker({
change: function () {
// some validations here
var i = 0;
var prev = "9/12/2014";
var date = kendo.toString(this.value(), 'd');
if (i == 0) {
$("#datepicker").data("kendoDatePicker").value(prev);
}
},
close: onClose,
open: onOpen
});
Updated Answer :
var date;
$(function () {
date = $("#datepicker").data("kendoDatePicker").value();
$("#datepicker").kendoDatePicker({
change: function () {
// some validations here
var i = 0;
var prev = date;
if (i == 0) {
$("#datepicker").data("kendoDatePicker").value(prev);
}
},
close: onClose,
open: onOpen,
});
})
I've used read only in the past to do this.
var endDate = $("#endDate").data("kendoDatePicker");
endDate.readonly();

Server Side Sorting using Mongoose (mongodb + node.js)

I am trying to sort based on a function. I am currently doing the following, and it works.
var _criteria = ... some search criteria
var _pageNumber = ... the page num I want to see
var _nPerPage = ... the number of documents per page
var _sort = {};
_sort.name = ... the column name I am sorting on
_sort.order = ... asc or desc sort
Collection.find(_criteria)
.skip((_pageNumber-1)*_nPerPage)
.limit(_nPerPage)
.sort(_sort.name,_sort.order)
.execFind(function (err, docs) {
...
});
Now I would like to sort based on some function that takes in a user input:
var sortFunc = function(x){ return (x - doc.score); };
// where doc.score is an attribute of the document I am searching on
// and x is a user provided value
and I can't find a way to do this. I tried to eval this function as follows:
var mongoose = require('mongoose');
var mdb = mongoose.connect(uri);
var myfunc = function(x){ return x; };
mdb.connection.db.eval( myfunc, "asdf", function (err, retval) {
console.log('err: '+err);
console.log('retval: '+retval);
});
but I get the following error:
err: Error: eval failed: db assertion failure
retval: null
Any help on this would be awesome.
Thanks a lot
I think you need do like this:
var mongoose = require('mongoose');
mongoose.connect(uri);
mongoose.connection.on("open", function(err){
mongoose.connection.db.eval("function(x){ return x; }", "asdf", function (err, retval) {
console.log('err: '+err);
console.log('retval: '+retval);
});
});
This can work on my PC. You must ensure that the connection is available.

Resources