2012-12-15 10 views
5

Mam poniższą funkcję, poniżej której używam do określenia pozycji użytkowników w tablicy wyników.Cloud Parse Limit 1000 pokonany przez Chaining?

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

.........

Jednak nie da dokładną odpowiedź, jeśli istnieje ponad 1000 wpisów, które spełniają kryteria, które. Chciałbym połączyć ze sobą zestaw metod .find, które mogę następnie wykonać na .count. Czy ktoś ma jakiś pomysł, jak mogę to osiągnąć? Jeśli mógłbyś podać przykład kodu, który byłby świetny!

Dziękujemy, James

+0

Należy również podać numer referencyjny usługi, z której korzystasz, więc może ktoś może Ci pomóc. –

+0

nazywa się Parse. www.parse.com – JamesLCQ

Odpowiedz

3

Parse.Query.count() nie ma wpływu na limit zapytań Parse.com 1000.

Dzięki temu otrzymasz poprawną liczbę wyników, niezależnie od tego, ile wpisów jest zgodnych z zapytaniem.

np

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 

punkty bonusowe - .limit() bierze liczbę jako parametr, a nie jako ciąg znaków w kodzie. https://www.parse.com/docs/js/symbols/Parse.Query.html#limit

HTH

+0

Cześć, dziękuję za tę odpowiedź. Mój fragment kodu nie jest zbyt jasny Zgadzam się. Pytanie brzmiało, że standardowe zapytanie Parse jest ograniczone do 1000. Jeśli potrzebujemy więcej rekordów niż to. Powiedzmy, że jest 1100, a następnie możemy wykonać liczenie, a następnie uruchomić dwa zapytania (drugi z pominięciem 1000). Moje pytania brzmią, jak połączyć oba wyniki w jeden obiekt wyników. Wielkie dzięki, James – JamesLCQ

+0

To powinno być całkiem proste - można użyć podkreślenia JS .union(), aby połączyć dwie lub więcej tablic wyników. [http://underscorejs.org/#union] – Meirion

+0

Czy na pewno ograniczenie 1000 nie ma zastosowania do liczenia? Dokumenty mówią, że tak, ale musi być KILKA sposób obejścia tego. Zastanawiam się, czy osobiście użyłeś licznika na ponad 1000 obiektach. –

3

Uważaj przy użyciu licznika. W przypadku zajęć z ponad 1000 obiektów operacje liczenia są ograniczone przez limity czasu. Mogą rutynowo powodować błędy limitu czasu lub zwracać wyniki, które są tylko w przybliżeniu poprawne. W związku z tym lepiej jest zaprojektować aplikację, aby uniknąć tego rodzaju operacji liczenia. I zazwyczaj użyć parametru pomijania tak:

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

Czy na pewno liczy się limit 1000? Wiem, że doktorzy mówią, że to robi, ale osoba odpowiadająca poniżej mówi, że to nie ma zastosowania. Zastanawiam się, czy osobiście natrafiłeś na problemy. –

+0

Tak, a zachowanie jest również dość dziwne. Nie dostaniesz żadnej wskazówki, że jesteś na granicy. –

+0

W obiekcie CloudCode nie ma obiektu okna. Jak działa ten kod poprawnie? –

5

Poniższa odpowiedź będzie działać w chmurze Kodeksu gdyż śledzi zliczania za pomocą parametru funkcji w kolejnych wezwań do getUserGlobalRank(). Z powodzeniem korzystałem z tej architektury w podobnych przypadkach.

Jak wspomniał w swoim komentarzu Gene Z. Ragan, obecnie zaakceptowana odpowiedź nie działa w Cloud Code, ponieważ nie ma obiektu "window".

Powodem, dla którego rekurencja została wyładowana do zwykłej funkcji JavaScript jest to, że funkcja Parse ma bardzo niski limit rekursji dla funkcji Cloud Code (zweryfikowałem, że> 4 wywołania rekursywne do funkcji Cloud Code spowoduje błąd). Implementując rekurencję w funkcji JavaScript, można ominąć rekurencyjny limit Parse i kontynuować wykonywanie wywołań rekursywnych, o ile kod zostanie wykonany w dozwolonym czasie (około 15 sekund).

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

Moim celem było powtórzenie wszystkich użytkowników w analizie składni. Oto moja odpowiedź na podstawie odpowiedzi keither04, która jest oparta na odpowiedź Cam Tullos za =]

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 .: Jestem ciekawy, czy jest to możliwe do zrobienia za pomocą obietnic.

0

Należy uznać, że powinno to zadziałać w zakresie realizacji obietnic. Ponadto, nie ma wątpliwości, że pominięcie jest obsługiwane tylko do 10 000, ale wcześniej popełniłem błąd. Pełne ujawnienie, nie testowałem tego kodu.

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

    } 
Powiązane problemy