Google 应用制作工具批量更新数据库记录
Google App Maker updating DB records in batches
我们有一个 Google App Maker 应用程序使用 Google Cloud SQL 表格。我们的位置是中欧的布拉格,app.saveRecords() 至少需要令人难以置信的 240 毫秒。我们尝试了很多方法,包括更改实例的位置,但都没有解决问题。
幸运的是,解决方案是批量插入新记录。我之前的帖子 [ ].
中的答案很好地解决了这个问题
如果有人为我们提供一个简单的代码来批量更新数据库中的记录,我们将不胜感激[服务器端脚本]。这样,我们不仅可以批量插入全新的记录,还可以快速更新已保存在数据库中的记录的数据。
假设我们有一个包含 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'];
...我们想使用关键字 "product code" 将可用性和价格数据分配给特定的数据库行。如果在数据库中没有找到产品代码,那么我们向数据库中插入一条新记录。
多个单行 inserts/updates 需要 Google 欧盟的 App Maker 用户太长时间,因为即使 SQL 实例位于欧盟,查询也会转到美国。 运行 这可能会分批打破目前 Google 美国以外的 App Maker 限制。非常感谢您的帮助,使 Google App Maker 成为世界各地初学者的绝佳工具。
这个问题可以通过使用正确的服务器脚本来解决,我强烈建议您阅读 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);
}
在线程中其他人的帮助下,我设法将插入或更新记录的时间减少到 50 毫秒。此外,我已经测试了 insert/update 10000 条记录到包含 60 个字段的 table。在这种情况下,速度为每条记录 60 毫秒。特此,我向任何人(可能会发现它有用的人)提供我的最终代码。感谢您提供所有有用的答案和评论!
/* 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);
}
我们有一个 Google App Maker 应用程序使用 Google Cloud SQL 表格。我们的位置是中欧的布拉格,app.saveRecords() 至少需要令人难以置信的 240 毫秒。我们尝试了很多方法,包括更改实例的位置,但都没有解决问题。
幸运的是,解决方案是批量插入新记录。我之前的帖子 [
如果有人为我们提供一个简单的代码来批量更新数据库中的记录,我们将不胜感激[服务器端脚本]。这样,我们不仅可以批量插入全新的记录,还可以快速更新已保存在数据库中的记录的数据。
假设我们有一个包含 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'];
...我们想使用关键字 "product code" 将可用性和价格数据分配给特定的数据库行。如果在数据库中没有找到产品代码,那么我们向数据库中插入一条新记录。
多个单行 inserts/updates 需要 Google 欧盟的 App Maker 用户太长时间,因为即使 SQL 实例位于欧盟,查询也会转到美国。 运行 这可能会分批打破目前 Google 美国以外的 App Maker 限制。非常感谢您的帮助,使 Google App Maker 成为世界各地初学者的绝佳工具。
这个问题可以通过使用正确的服务器脚本来解决,我强烈建议您阅读 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);
}
在线程中其他人的帮助下,我设法将插入或更新记录的时间减少到 50 毫秒。此外,我已经测试了 insert/update 10000 条记录到包含 60 个字段的 table。在这种情况下,速度为每条记录 60 毫秒。特此,我向任何人(可能会发现它有用的人)提供我的最终代码。感谢您提供所有有用的答案和评论!
/* 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);
}