ios - 如何将数千个对象保存到 Parse.com?

标签 ios objective-c parse-platform

关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。












想改进这个问题?将问题更新为 on-topic对于堆栈溢出。

7年前关闭。




Improve this question




在我使用 Parse 的 iOS 应用程序中,一些用户需要在一个操作中保存数千个对象。我已经尝试遍历数据数组并一个一个地创建/保存对象,但这会导致对象保存到我的数据浏览器的速度非常慢。每个对象只需要包含几个字符串,所以我不明白为什么要花这么长时间来保存这些对象。

有没有更快的方法将数千个对象保存到 Parse?

最佳答案

编辑:

我一直使用 [PFObject saveAllInBackground:array block:^(BOOL succeeded, NSError *error) {}];但是....另一种我刚刚尝试成功的方法是将Json字符串上传为PFFile(没有128k限制),然后使用云代码对其进行解析并创建必要的PFObject。我能够以少量使用它,但不幸的是,当使用大量时,云代码会超时。相反,我选择使用后台作业来执行解析。这需要相当长的时间才能使数据完全可用,但可以处理大量数据。上传时间本身要快得多。当使用 1000 个对象和 3 个字符串时,每次上传大约需要 0.8 秒,而在后台保存所有对象需要 23 秒,5000 个对象和 3 个字符串每个上传时间仅为 2.5 秒。除了更快的时间,您还可以获得进度更新。根据用例,如果立即快速上传很重要,而不是让数据立即可用,则使用此替代方案可能效果最佳。

IOS代码:

  NSMutableArray *array = [NSMutableArray array];
    for (int i = 0; i<5; i++) {
        //subclass of PFObject
        Employee *employee = [Employee object];
        employee.firstName = @"FName";
        employee.lastName = @"LName";
        employee.employeeID = @"fid54";
        [array addObject:[employee dictionaryWithValuesForKeys:employee.allKeys]];
    }
    //Seperate class only to store the PFFiles
    PFObject *testObject = [PFObject objectWithClassName:@"fileTestSave"];
    testObject[@"testFile"] = [PFFile fileWithData:[NSJSONSerialization dataWithJSONObject:array options:0 error:nil]];

    NSLog(@"started");
    //**notice I am only saving the test object with the NSData from the JSONString**
    [testObject saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
        if (!error && succeeded) NSLog(@"succeeded");
        else NSLog(@"error");
    }];

编辑:不是保存可能导致超时问题的 beforeSave 或 afterSave 云代码,而是可以随时运行下面的后台作业。它抓取“fileTestSave”表中的所有行,解析这些行中的 JSON 字符串,并将它们添加到“Person”表中。完成后,它将从表中取出行。全部异步!
var _ = require('underscore.js');
Parse.Cloud.job("userMigration", function(request, status) 
{

    // Set up to modify user data
    Parse.Cloud.useMasterKey();
    //Table called fileTestSave stores a PFFile called "testFile" which we will use an HTTPRequest to get the data. Is there a better way to get the data?
    //This PFFile stores a json string which contains relavent data to add to the "Person" table
    var testFileSave = Parse.Object.extend("fileTestSave");
    var query = new Parse.Query(testFileSave);
    query.find().then(function(results) 
    {
        //Generate an array of promises
        var promises = [];

        _.each(results, function(testFileSaveInstance){
            //add promise to array
            promises.push(saveJsonPerson(testFileSaveInstance));
        });
        //only continue when all promises are complete
        return Parse.Promise.when(promises);
    }).then(function() 
    {

    // Set the job's success status
        console.log("Migration Completed NOW");
        status.success("Migration completed");
    }, function(error) {
    // Set the job's error status
        status.error("Uh oh, something went wrong.");
    });
});

function saveJsonPerson(fileTestSave)
{
    //Get the pffile testfile
    var testFile = fileTestSave.get("testFile");
    //get the fileURL from the PFFile to generate the http request
    var fileURL = testFile["url"]();
    //return the promise from the httpRequest
    return Parse.Cloud.httpRequest({
        method:"GET",
        url: fileURL
    }).then(function(httpResponse){
            //return the promise from the parsing
            return parsehttpResponse(httpResponse,fileTestSave);
        },
        function(error){
            console.log("http response error");
        }
    );
}

function parsehttpResponse(httpResponse,fileTestSave)
{   
    var jsonArray = eval( '(' + httpResponse.text + ')' );
    var saveArray =[];

    //parse each person in the json string, and add them to the saveArray for bulk saving later.
    for (i in jsonArray) 
    {
        var personExtend = Parse.Object.extend("Person");
        var person = new personExtend();
        person.set("classDiscriminator",jsonArray[i]["classDiscriminator"]);
        person.set("lastName",jsonArray[i]["lastName"]);
        person.set("firstName",jsonArray[i]["firstName"]);
        person.set("employeeID",jsonArray[i]["employeeID"]);
        saveArray.push(person);
    };
    //return the promise from the saveAll(bulk save)
    return Parse.Object.saveAll(
            saveArray
        ).then(function(){
                //return the promise from the destory
                return fileTestSave.destroy(

                    ).then(function(){

                    },function(error){
                            console.log("error destroying");
                        }
                );
        },function(error){
                console.log("Error Saving");
            }
    );
}

作为引用超时的旧云代码:
Parse.Cloud.afterSave("fileTestSave", function(request) {

    //When accessing PFFiles you don't get the actual data, there may be an easier way, but I just utitlized an HTTPRequest to get the data, and then continued parsing.
    var file = request.object.get("testFile");
    var fileURL = file["url"]();
    console.log("URL:"+fileURL);
    Parse.Cloud.httpRequest({
            method:"GET",
            url: fileURL,
            success: function(httpResponse) 
            {
                var jsonArray = eval( '(' + httpResponse.text + ')' );
                var saveArray =[];
                for (i in jsonArray) 
                {
                    var personExtend = Parse.Object.extend("Person");
                    var person = new personExtend();
                                    //May be a better way to parse JSON by using each key automatically, but I'm still new to JS, and Parse so I set each individually.
                    person.set("classDiscriminator",array[i]["classDiscriminator"]);
                    person.set("lastName",array[i]["lastName"]);
                    person.set("firstName",array[i]["firstName"]);
                    person.set("employeeID",array[i]["employeeID"]);
                    saveArray.push(person);
                };
                Parse.Object.saveAll(saveArray,
                {
                    success: function(list) {
                      // All the objects were saved.
                    },
                    error: function(error) {
                      // An error occurred while saving one of the objects.
                    },
                });
            },
            error: function(httpResponse) {
            console.log("http response error");
            }
    });
});

关于ios - 如何将数千个对象保存到 Parse.com?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23841017/

相关文章:

ios - Sdk 用于获取在 facebook/twitter/linked 上发布的授权 token ,然后使用 nodejs 发布

ios - 属性(property)观察员 (KVO) : are they still the way to go?

android - 使用parse.com facebook登录 - 获取参数third_party_app_id必须是有效的应用程序id

ios - 在 Parse.com 中存储 UIView

ios - 如何调试静默远程通知

ios - XMPPFramework IOS - 实现 MUC

ios - 创建一个外部网络服务并在 viewdidload 中调用它

iphone - 如何在 UIImageView 中显示高分辨率图像

iphone - "What were you doing when the app crashed?"恢复

objective-c - 如何使用 Parse 中的查询检查值是否存在于 2 个不同的字段中?