Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cloud Code Parse Limit 1000 overcome with Chaining?

I have the following function below which I am using to determine a users rank in a scoreboard.

Parse.Cloud.define("getUserGlobalRank", function(request, response) 
{
    var usernameString = request.params.username;
    var scoreAmount = request.params.score;

    var globalRankQuery = new Parse.Query("scoreDB");
        globalRankQuery.greaterThanOrEqualTo("score",scoreAmount);  
        globalRankQuery.descending("score");
        globalRankQuery.limit("1000");
        globalRankQuery.count(
        {
        success: function(count);
        {
            response.success(count);                
        },

.........

However this will not give an accurate response if there are more than 1000 entries that meet that criteria. I would like to chain together a set of .find methods that I can subsequently perform a .count on. Does anyone have any idea how I can achieve this? If you could provide a code example that would be great!

Many thanks, James

like image 705
JamesLCQ Avatar asked Dec 15 '12 21:12

JamesLCQ


People also ask

What is parse cloud code?

Cloud Code is easy to use because it’s built on the same Parse JavaScript SDK that powers thousands of apps. The only difference is that this code runs in your Parse Server rather than running on the user’s mobile device. When you update your Cloud Code, it becomes available to all mobile environments instantly.

What happens when I make changes to my Cloud code?

The more of your Cloud Code you cover, the more you can be assured that changes don’t have any unforeseen consequences. Traditionally, you have to restart your Parse Server whenever you make changes to Cloud Code. Now, you can type npm run watch, and your Parse Server will auto-restart when any affected files are changed.

How many times can you write code with cloud code?

Rather than writing code once for each client environment, you can write it just once with Cloud Code. Let’s take a look at our movie review example. When you’re choosing how many stars to give something, you can typically only give 1, 2, 3, 4, or 5 stars.

How do I write better cloud code?

These are only a few examples of how to write better Cloud Code. You can learn more about new ES6, ES7, ES8, and other ES release features here. On the latest Parse Server Example project, you can now run npm run prettier to style your code, followed by npm run lint , which will run over your Cloud Code and check for quality issues.


3 Answers

The following answer will work in Cloud Code as it keeps track of the count by using a function parameter in successive calls to getUserGlobalRank(). I have used this architecture in similar cases successfully.

As Gene Z. Ragan mentioned in his comment, the currently accepted answer will not work in Cloud Code because there is no 'window' object.

The reason that recursion has been offloaded to a regular Javascript function is because Parse has a very low recursion limit for Cloud Code functions (I have verified that >4 recursive calls to a Cloud Code function will result in an error). By implementing the recursion in a Javascript function, you can bypass Parse's recursive limit, and continue making recursive calls as long as the code executes in the permitted time (about 15 seconds).

Parse.Cloud.define('getUserGlobalRank', function(request, response) {
     getUserGlobalRank({'username':request.params.username, 'score':request.params.score}, {
        success: function(count) {
            response.success(count);
        },
        error: function(error) {
            response.error(error);
        }
    }); 
});

function getUserGlobalRank(request, response) {

    var usernameString = request['username'];
    var scoreAmount = request['score'];
    var count = (request['count'])? request['count'] : 0;

    var globalRankQuery = new Parse.Query("scoreDB");
    globalRankQuery.greaterThanOrEqualTo("score", scoreAmount);  
    globalRankQuery.descending("score");
    globalRankQuery.limit(1000);
    globalRankQuery.skip(count);
    globalRankQuery.find({
        success: function(results) {
            if (results.length > 0) {
                count = count + results.length;
                getUserGlobalRank({'count':count, 'username':usernameString, 'score':scoreAmount}, response);
            }
            else { // found count of users with higher ranks
                response.success(count);
            }
        },
        error: function(error) { // query error
            response.error(error);
        }
    });
}
like image 176
keither04 Avatar answered Oct 07 '22 15:10

keither04


My goal was to iterate through all users on Parse. Here's my answer based on keither04's answer that is based on Cam Tullos's answer =]

Parse.Cloud.job("checkUsers", function (request, response) 
{
    // {} - empty params for first iteration
    getAllUsers({}, {
        success: function (users) {
            // Do stuff with users
            response.success("Loaded " + users.length + " users");
        },
        error: function (error) {
            response.error(error);
        }
    });
});

function getAllUsers (request, response) 
{
    var users = (request["users"]) ? request["users"] : [];
    var skip = users.length;
    var userQuery = new Parse.Query(Parse.User);
    userQuery.limit(1000);
    userQuery.skip(skip);
    userQuery.find({
        success: function (results) {
            if (results.length > 0) {
                var allUsers = users.concat(results);
                var params = {"users": allUsers};
                getAllUsers(params, response);
            } else {
                response.success(users);
            }
        },
        error: function (error) {
            response.error(error);
        }
    });
}

P.S.: I'm curious if it's possible to do using promises.

like image 4
derpoliuk Avatar answered Oct 07 '22 15:10

derpoliuk


Parse.Query.count() is not affected by the Parse.com 1000 query limit.

So you will get a correct count returned no matter how many entries matched by the query.

eg:

var userQ = new Parse.Query('_User');
userQ.count({success:function(count){console.log(count)}});
> 1512

var userQ = new Parse.Query('_User');
userQ.limit(100);
userQ.count({success:function(count){console.log(count)}});
> 1512

Bonus points - .limit() takes a number as its parameter, not a string as in your code. https://www.parse.com/docs/js/symbols/Parse.Query.html#limit

hth

like image 3
Meirion Avatar answered Oct 07 '22 15:10

Meirion