2012-12-15 10 views
5

以下の機能を使用して、スコアボードのユーザーランクを決定しています。クラウドコードの解析の制限1000はチェインで克服できますか?

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);     
     }, 

.........

その基準に満たしている1000個の以上のエントリがある場合は、これは正確な応答を与えることはありません。後で.countを実行できる.findメソッドのセットを連鎖したいと思います。どのように私はこれを達成することができます誰も考えを持っていますか?あなたがコード例を提供することができれば素晴らしいでしょう!

多くのおかげで、 ジェームズ

+0

また、使用しているサービスのリファレンスを提供してください。だれかがあなたを助けるかもしれません。 –

+0

これをParseといいます。 www.parse.com – JamesLCQ

答えて

3

Parse.Query.countは()Parse.com 1000年クエリ制限の影響を受けません。

クエリで一致するエントリの数に関係なく、正しいカウントが返されます。

例:

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 

ボーナスポイント - .limit()は、あなたのコードのように、文字列、そのパラメータとして数値をとりません。 https://www.parse.com/docs/js/symbols/Parse.Query.html#limit

HTH

+0

こんにちは、ありがとうございます。私のコードスニペットはあまり明確ではありません。問題は、実際には、標準のParseクエリが1000で制限されていることです。これ以上のレコードが必要な場合です。 1100があり、カウントを実行してから2つのクエリを実行できるとします(2番目のクエリは1000のスキップで実行されます)。私の質問は、どのように2つの結果を1つの結果オブジェクトに結合するかということです。多くのありがとう、James – JamesLCQ

+0

これは非常に簡単なはずです。アンダースコアJSの.union()を使って2つ以上の結果配列を結合することができます。 [http://underscorejs.org/#union] – Meirion

+0

1000の制限はカウントに当てはまりませんか?ドキュメントはそう言いますが、これを回避する方法がいくつかあります。ちょうどあなたが1000以上のオブジェクトで個人的に使用回数を実行したかどうか疑問に思っています。 –

3

数を使用する場合に注意してください。オブジェクトが1000を超えるクラスの場合、カウント操作はタイムアウトによって制限されます。日常的にタイムアウトエラーが発生したり、ほぼ正しい結果しか返されない場合があります。したがって、この種のカウント操作を避けるためにアプリケーションを設計することが望ましいです。私は一般的にそうように、スキップ・パラメータを使用します。それはgetUserGlobalRankに連続呼び出しで関数パラメータを使用して、カウントを追跡して

Parse.Cloud.define('getUserGlobalRank', function(request, response) { 

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

if (skip == 0 || !window['results']) { window['results'] = []; } 

var qry = new Parse.Query('scoreDB'); 
qry.greaterThanOrEqualTo('score', scoreAmount); 
qry.descending('score'); 
qry.limit(1000); 
qry.skip(skip); 
qry.find({ 
    success: function (results) { 
     if (results.length > 0) { // got results.. 
      window.results = window.results.concat(results); 

      // Call the function again 
      var params = request.params; 
      params['skip'] = window.results.length; 
      request.params = params; 
      Parse.Cloud.run('getUserGlobalRank', request, response); 

     } else { // we're done here 
      response.success(window.results); 
     } 
    }, 
    error: function (err) { 

    } 
}); 
}); 
+0

カウント数に1000の制限が存在しますか?私はドキュメントがそうであると言うことを知っていますが、以下に答える人はそれが適用されないと言います。あなたが個人的に問題に遭遇したかどうかは不思議です。 –

+0

はい、その動作はむしろ変です。あなたは、あなたが限界に遭っているという兆候も見られません。 –

+0

CloudCodeで使用可能なウィンドウオブジェクトがありません。このコードはどのように正しく機能していますか? –

5

次の答えは(クラウドコードで動作します)。私はこのアーキテクチャを同様のケースでうまく使用しました。

Gene Z. Raganが彼のコメントで述べたように、現在受け入れられている回答は、「ウィンドウ」オブジェクトがないためクラウドコードでは機能しません。

通常のJavascript関数に再帰がオフロードされるのは、Parseのクラウドコード関数の再帰制限が非常に小さいためです(クラウドコード関数への4回以上の再帰呼び出しでエラーが発生することが確認されています)。 Javascript関数で再帰を実装することで、Parseの再帰的制限をバイパスし、コードが許可された時間(約15秒)で実行される限り再帰呼び出しを続けることができます。

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); 
     } 
    }); 
} 
4

私の目標は、Parseですべてのユーザーを繰り返したことでした。ここでカムTullosの回答に基づいているkeither04の回答に基づいて私の答え=]

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だ:それは約束を使用して行うことは可能だ場合、私は好奇心が強いです。

0

これは、約束を履行する限り有効です。また、skipはあいにく10,000までしかサポートされていませんが、以前は間違っていました。完全な開示、私はこのコードをテストしていません。

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

    }); 

    function getAllUsers(request) { 
     // 
     var users = (request["users"]) ? request["users"] : []; 
     var skip = users.length; 
     var userQuery = new Parse.Query(Parse.User); 
     userQuery.limit(1000); 
     userQuery.skip(skip); 

     Parse.Promise.as().then(function() { 
     // 
     return userQuery.find().then(null, function(error) { 
      // 
      return Parse.Promise.error(error); 

     });  

     }).then(function(userObjects) { 
     // 
     if (userObjects.length > 0) { 
      var allUsers = users.concat(userObjects); 
      var params = {"users": allUsers}; 
      getAllUsers(params); 
     } else { 
      // 
      return Parse.Promise.resolve(allUsers); 
     }  

     }, 
     function(error) { 
     // 
     return Parse.Promise.reject(error); 
     }); 

    } 
関連する問題