在解析服务器中,我有一个名为Stats
的类,其中包含列secondsPlayed
(数字)和timeScore
(数字)
我正在使用云代码更新timeScore
列中的所有行
下面的代码仅在更新和保存1个或2个对象results.length
时有效。如果Parse.Query返回的结果超过2,则代码崩溃,并且出现以下错误。
error: Failed running cloud function timeScore for user undefined with:
Input: {}
Error: {"code":101,"message":"Object not found."} functionName=timeScore, code=101, message=Object not found., , user=undefined
error: Error generating response. ParseError { code: 101, message: 'Object not found.' } code=101, message=Object not found.
error: Object not found. code=101, message=Object not found.
这是个问题,因为我需要更新和保存数千个对象。最好和最快的方法是什么?
为什么我的代码只能用于2个对象,但不能用于2个以上?我怎样才能解决这个问题?
这是我的代码
var _ = require("underscore");
Parse.Cloud.define("timeScore", function(request, response) {
var query = new Parse.Query("Stats");
query.greaterThan("secondsPlayed", 1000);
query.find().then(function(results) {
_.each(results, function(result) {
var secondsPlayed = result.get("secondsPlayed") || 0;
result.set("timeScore", secondsPlayed*2);
});
return Parse.Object.saveAll(results);
}).then(function(results) {
response.success(results);
}, function(error) {
response.error(error);
}); });
这就是我的称呼
#!/usr/bin/env node
var Parse = require("parse/node");
Parse.initialize("xx", "xx");
Parse.serverURL = "http://randomapp.herokuapp.com/parse";
Parse.Cloud.run('timeScore');
更新:
下面是我的最新代码。一切正常,除了我没有明显原因而收到以下错误的事实。
heroku[router]: at=error code=H12 desc="Request timeout" method=POST path="/parse/functions/timeScore
无论选择什么batchSize,我都会收到超时错误,并且每30秒就会收到一次。我一共得到了5次。第五次以后,我不再明白了。我在处理大约2.5分钟(30秒* 5)时遇到了第五个也是最后一个错误。此错误不会以任何方式影响该过程。不论batchSize如何,所有250k对象都将更新和保存。
我想可能是因为我从未致电results.error
或results.success
,服务器认为我仍在做一些工作并显示错误。但是,我按照以下方式更新了代码,但仍然收到超时错误。
还在每个超时错误之后,从开始处再次调用processBatch()。由于我收到5个超时错误,processBatch()被调用了5次。因此,在第五次超时错误之后,有5个processBatch()函数同时运行(我通过日志确认了这一点)。
是什么导致我收到的heroku超时错误?我该如何解决?
var _ = require("underscore");
Parse.Cloud.define("timeScore", function(request, response) {
var counter = 0;
function processBatch(query, batchSize, startingAt, process) {
query.limit(batchSize);
query.skip(startingAt);
return query.find().then(results => {
return process(results).then(() => results.length);
}).then(length => {
return (length === batchSize)? processBatch(query, batchSize, startingAt+length, process) : {};
});
}
function setTimeScores(stats) {
console.log("LENGTH " + stats.length);
_.each(stats, stat => {
counter ++;
stat.set("timeScore", counter);
});
return Parse.Object.saveAll(stats);
}
var query = new Parse.Query("Stats");
processBatch(query, 2500, 0, setTimeScores).then(results => {
response.success(results);
}).catch(error => {
response.error(error);
});
});
答案 0 :(得分:1)
要处理大于最大查询限制的对象数,请构建一个更抽象的函数,该函数使用查询的limit()
和skip()
来游标数据:
function processBatch(query, batchSize, startingAt, process) {
query.limit(batchSize);
query.skip(startingAt);
return query.find().then(results => {
return process(results).then(() => results.length);
}).then(length => {
return (length === batchSize)? processBatch(query, batchSize, startingAt+length, process) : {};
});
}
这表示,获取batchSize
指定的query
长对象,然后对检索到的对象进行处理,然后,如果可能更多,请再次执行相同的操作,跳过我们已经处理过的对象。
您的处理步骤如下:
function setTimeScores(stats) {
_.each(stats, stat => {
var secondsPlayed = stat.get("secondsPlayed") || 0;
stat.set("timeScore", secondsPlayed*2);
});
return Parse.Object.saveAll(stats);
}
这样称呼它:
let query = new Parse.Query("Stats");
query.greaterThan("secondsPlayed", 1000);
processBatch(query, 100, 0, setTimeScores);
EDIT 在云功能的上下文中,这样称呼它...
Parse.Cloud.define("computeStats", function(request, response) {
let query = new Parse.Query("Stats");
query.greaterThan("secondsPlayed", 1000);
processBatch(query, 100, 0, setTimeScores).then(results => {
response.success(results);
}).catch(error => {
response.error(error);
});
});