I'm still learning how to use Parse and I'm working with migrating a subset of a database with 49 items. I read that Parse saveAll should be able to handle batches of 70-100 with no issues but when ever I run the code below, Parse always only saves 20 items.
I run a query to draw out all items with .each(), then I create new parse Objects and insert them into an array.
Once the each() finishes, the array contains all 49 elements but when saveAll runs, only 20 items are saved.
I read thru promises but I'm not certain how they'll work with saveAll, additionally, most people here don't seem to be having any issues with saveAll.
I've tested the code below as a background and cloud function.
Parse.Cloud.job("testEach2", function(request, response) {
var eachQuery = new Parse.Query("test_csv");
var Item = Parse.Object.extend("Item");
var toSave = [];
eachQuery.each(
function(result) {
var item = new Item();
item.set("name",result.get("v_products_name_1"))
console.log(item.name)
toSave.push(item)
}, {success: function(result) {
response.success();
console.log(toSave.length);
Parse.Object.saveAll(toSave).then(function(results){
console.log("Objects were saved!");
response.success("Awesome");
},function(error){
console.log(error);
response.error(error);
});
}, error: function() {} });
});
You should call response.success(); only after Parse.Object.saveAll() is finished. Remove the first response.success(); from your success callback.
Related
I saw from http://profi.co/all-the-limits-of-parse/ that one of the limitations of Parse is:
scheduled jobs can last a maximum of 15 minutes, but you have to put ALL of your code in one function (which basically makes it unreadable for later usages)
Is this true? Has anybody verified that you don't get the same 15 minutes of run time if we split the job up into functions?
I have my cloud code in a file like this:
module.exports = function(request, status) {
var query = new Parse.Query(ParseClass);
query.each(function(classObject){
return doSomething(classObject).then(function(data),{
//success code
}, function(error){
//error code
});
}).then(function(){
//success code
}, function(error){
//error code
});
function doSomething(classObject){
var promise = new Parse.Promise();
someOtherFunction(classObject.get('variable')).then(function(data){
promise.resolve(data);
}, function(error){
promise.reject(data);
});
return promise;
}
function someOtherFunction(){
//code
}
}
It runs fine and hasn't failed.
I have a small afterSave trigger in my parse cloud code. The trigger just re-counts items that are flagged as deleted=false.
When I update my object, the count goes just fine, except when I update the deleted flag. It seems like the count is considering objects BEFORE the save event, which is not what I would expect from an "afterSave" trigger.
On the other hand, by using a "find" instead of a "count" on the very same query, I will always get the right number of objects. Of course the "find" way will go just when the query stays below 1000 objects.
Is there something wrong in my code? Is it the expected behavior? Is it a bug? Any alternative way to count objects the right way?
Thank you so much for your attention
Parse.Cloud.afterSave("BranchLike", function(request) {
console.log("Managing branchLike after save...");
Parse.Cloud.useMasterKey();
var branch = request.object.get("branch");
var branchLikeClass = Parse.Object.extend("BranchLike");
var type = request.object.get("type");
var branchLikeQuery = new Parse.Query(branchLikeClass);
branchLikeQuery.equalTo("branch",branch);
branchLikeQuery.equalTo("deleted",false);
branchLikeQuery.equalTo("type",type);
branchLikeQuery.count({
success: function(count) {
console.log("count = "+count); //works fine except on "delete" flag updates
/* ... */
},
error: function(error) {
/* ... */
}
});
branchLikeQuery.find({
success: function(branchLikes) {
console.log("ALTERNATIVE COUNT = "+branchLikes.length); //works fine when having less than 1000 objects
},
error: function(error) {
/* ... */
}
});
});
I have written a cloud code to change a Boolean value in table. The code is getting executed and the values are getting updated as well. But the issue is that I get the following error printed in my console. I am worried if this might cause a problem if the number of rows increase. Following is the error which is being printed on the console
I2015-09-15T06:15:48.317Z]v11: Ran job hello with:
Input: {}
Failed with: Error: Job status message must be a string
at updateJobMessageAndReturn (<anonymous>:1157:7)
at Object.success (<anonymous>:1211:9)
at e.obj.save.success (main.js:25:30)
at e.<anonymous> (Parse.js:12:27827)
at e.s (Parse.js:12:26759)
at e.n.value (Parse.js:12:26178)
at e.<anonymous> (Parse.js:12:26831)
at e.s (Parse.js:12:26759)
at e.n.value (Parse.js:12:26178)
at e.s (Parse.js:12:26887)
Following is the cloud code:
Parse.Cloud.job("hello", function(request, response) {
Parse.Cloud.useMasterKey();
var presentDate = new Date();
// presentDate.setDate(presentDate.getDate()-1);
presentDate.setHours(0,0,0,0);
var usersValid = new Parse.Query(Parse.User);
usersValid.equalTo("emailVerified", true);
//usersValid.greaterThan("updatedAt", presentDate);
var users = new Parse.Query("Properties");
users.matchesQuery("user",usersValid);
users.equalTo("verified", false);
users.limit(1000);
users.find({
success: function(results) {
console.log("Total new properties "+ results.length);
for (var i = 0; i < results.length; i++) {
var obj = results[i];
obj.set("verified", true);
obj.save(null,{
success: function (object) {
console.log("Success - "+i);
response.success(object);
},
error: function (object, error) {
console.log("Failed - "+i);
response.error(error);
}
});
}
},
error: function(error) {
console.log("failed");
}
});
When you call
response.success(object);
you're passing the full object that was just saved - but you shouldn't be. You can just call success with a simple status string, like 'OK', or with some element from the saved object, like its object id.
The more serious issue is that you're requesting 1000 items in the query and then updating and saving each individually - and in the save completion handler you're calling success or error. So, as soon as the first of those 1000 objects is saved you're telling the job it's complete and it can stop processing the rest.
You should change your job to use promises instead of old style callbacks and you should put all of the save promises into an array and wait for them to complete after your loop before you call success or error.
I'm trying to execute the following in cloud code:
Parse.Cloud.job("fixUserStuffs", function(request, status) {
Parse.Cloud.useMasterKey();
var query = new Parse.Query(Parse.User);
query.limit(1000);
query.each(function(user) {
user.set('password', 'abc');
return user.save();
}).then(function() {
status.success("completed successfully.");
}, function(error) {
status.error(error);
});
but it's returning me the error 'Failed with: Cannot iterate on a query with sort, skip, or limit.' This seems kind of pointless to me since I either need to skip or increase the number of objects returned rather than the default 100.
When you use Parse.Query.each(), it will process ALL records. 1, 1000, 1000000. It doesn't matter.
If you don't want to process all records, then you don't use each.
I send a request to parse that includes a Comment object that has a pointer to a User named "from".
In afterSave I need to read this and I'm having all kinds of problems. beforeSave works just fine, but I want to execute this code in afterSave;
Parse.Cloud.afterSave("Comment", function(request) {
var userQuery = new Parse.Query("User");
userQuery.get(request.object.get("from").id, {
success: function(user) {
},
error : function(error) {
console.error("errrrrrrrr" + error);
}
});
});
Here is the log I'm seeing on parse
errrrrrrrrr [object Object]
EDIT:
I also tried
var userQuery = new Parse.Query("_User");
Seems like I had to call useMasterKey, since I was fetching a user data.
I'm not entirely sure about this though so I'll keep this question open.
Parse.Cloud.useMasterKey();
Have you tried this?
var userQuery = new Parse.Query(Parse.User);
Try to fetch the pointer directly:
var fromUserPointer = request.object.get("from");
fromUserPointer.fetch().then(function(fetchedFromUser){
},function(error){
});
Slightly different approach.
This assumes that you have the comment object available right there, or at least its id.
Instead of querying the User collection, how about this:
var commentQuery = new Parse.Query("Comment");
commentQuery.include("from");
commentQuery.get(<commentId>, {
success: function (comment)
{
var user = comment.get("from"); // Here you have the user object linked to the comment :)
},
error: function (error)
{
console.log("ERROR: ");
console.log(error);
}
});