Google App Maker批量更新数据库记录

时间:2019-04-02 11:48:39

标签: google-app-maker

我们有一个使用Google Cloud SQL表的Google App Maker应用。我们的位置在中欧的布拉格,app.saveRecords()最少需要240ms。我们已经尝试了许多方法,包括更改实例的位置,但是并不能解决问题。

幸运的是,解决方案是分批插入新记录。我以前的线程[Google App Maker saving records to DB is taking 240ms per record]中的答案很好地解决了这个问题。

如果有人为我们提供了一个简单的代码来批量更新数据库中的记录[服务器端脚本],我们将非常感激。这样,我们不仅可以批量插入全新的记录,而且可以快速更新已经保存在数据库中的记录数据。

假设我们有一个包含3个自定义字段的数据库:

product code | product availability | price

+ 带有数据的示例数组:

ourData[0] = ['pc001','in stock','99'];
ourData[1] = ['pc002','out of stock','49'];
ourData[2] = ['pc003','out of stock','199'];
ourData[3] = ['pc004','in stock','149'];
ourData[4] = ['pc005','in stock','299'];

...,我们想使用键“产品代码”将可用性和价格数据分配给特定的数据库行。如果在数据库中找不到产品代码,那么我们将新记录插入数据库。

多次单行插入/更新会使EU中的Google App Maker用户花费太长时间,因为即使SQL实例位于欧盟中,查询也确实会转到美国。批量运行此程序可能会打破当今美国以外的Google App Maker限制。非常感谢您为使Google App Maker成为全球初学者的绝佳工具所提供的帮助。

2 个答案:

答案 0 :(得分:2)

在线程中其他人的帮助下,我设法将插入或更新记录的时间减少到50ms。此外,我测试了将10000条记录插入/更新到包含60个字段的表中。在这种情况下,每条记录的速度为60ms。在此,我向任何人(可能会觉得有用)提供我的最终代码。感谢您提供所有有用的答案和评论!

/* We use Google Cloud SQL Table "testDB" that contains these fields:
   - Id (the default primary key for DBs in Google App Maker)
   - productCode
   - availability
   - price

   We have an array called "data" which contains the data [productCode, availability, price] we want to save to the database.
*/

function saveDataNew(){
    var data = [];
    data[0] = ['pc1','in stock','99'];
    data[1] = ['pc2','out of stock','129'];
    data[2] = ['pc3','in stock','78'];
    data[3] = ['pc4','in stock','95'];

    //load all the records in the DB (no filter is used)
    var query = app.models.testDB.newQuery();
    var records = query.run();
    console.log("Found " + records.length + " records in the database.");

    //create an array to help us find DB's Id for each unique productCode.
    var helpingArray = [];
    for (var x in records) {
      var product = records[x]; //get each record in the DB
      helpingArray.push([product.productCode,product.Id]); //save this record's productCode and Id into the helping array
    }

    //setting up the writing in batches
    var totalRecords = data.length;
    var batchLimit = 500; //size of a batch round - number of lines for each app.saveRecords();
    var roundlimit;
    if(totalRecords < batchLimit){
      roundlimit = totalRecords;
    }
    else{
      roundlimit = batchLimit;     
    }
    var totalRounds = Math.ceil(totalRecords / batchLimit);
    var round = 1;
    var currentItem = 0;

    //start writing in batches
    do{ 
        var recordsToSave = [];
        //create or update a record in the DB for each line of our data within one batch round
        for(var i=currentItem; i<roundlimit; i++){
          var wantedCode = data[i][0]; //get the productCode of the current line of the data array
          var orderNum = -1; //create a variable to find the order number of the productCode in the helping array
          for(var z=0; z<helpingArray.length; z++){ //search for the productCode in the helping array
            if(helpingArray[z][0]==wantedCode){
              orderNum = z; //save the line's number if the productCode is found in the helpingArray
              continue;
            }
          }
          var productRecord;
          if (orderNum == -1){ //there was no line with the productCode found the helpingArray => create a new record
                productRecord = app.models.testDB.newRecord();
                productRecord.productCode = data[i][0]; 
          }
          else{ //the productCode was found in the helpingArray => edit the existing record in the DB 
                productRecord = records[orderNum];
          }
          //provide the record with the data
          productRecord.availability = data[i][1];
          productRecord.price = data[i][2];

          //cumulate records and save them once the batch round is finished
          recordsToSave.push(productRecord); 
        }

        //a batch round has been finished, save records if there are any
        if(recordsToSave.length){
            console.log("Records saved: "+recordsToSave.length);
            app.saveRecords(recordsToSave);
        }

        currentItem += batchLimit;
        round++; 

        if (totalRecords < round*batchLimit){
          roundlimit = totalRecords;  
        }
        else{
          roundlimit += batchLimit;    
        }
    } while(round <= totalRounds);
}

答案 1 :(得分:0)

可以使用适当的服务器脚本来解决此问题,我强烈建议您阅读official documentation中的服务器脚本的工作方式。请密切注意查询记录示例。

因此,以前面的解决方案示例为基础,可以对其进行略微修改以实现您的需求。这是它的外观:

function saveData(){

    //get the data
    var data = getData();

    var totalRecords = data.length;
    var batchLimit = 2000;
    var totalRounds = Math.ceil(totalRecords / batchLimit);
    var round = 1;
    var roundlimit = batchLimit;
    var currentItem = 0;

    do{
        var recordsToSave = [];

        for(var i=currentItem; i<roundlimit; i++){

            var recordData = data[i];
            var productCode = recordData[0];

            //check if the record already exists
            var query = app.models.testDB.newQuery();
            query.filters.productCode._equals = productCode;
            var productRecord = query.run()[0];

            //if non existent, create a new one
            if(!productRecord){
                productRecord = app.models.testDB.newRecord();
                productRecord.productCode = productCode;
            }

            productRecord.availability = recordData[1];
            productRecord.price = recordData[2];
            recordsToSave.push(newProduct);
        }

        if(recordsToSave.length){
            app.saveRecords(recordsToSave);
        }

        currentItem += batchLimit;
        roundlimit += batchLimit;
        round++;

    } while(round <= totalRounds);

}