Google App Maker обновляет записи БД в пакетном режиме - PullRequest
0 голосов
/ 02 апреля 2019

У нас есть приложение Google App Maker, использующее таблицы Google Cloud SQL.Наше местоположение - Прага, Центральная Европа, и app.saveRecords () занимает минимум 240 мс.Мы пробовали много вещей, включая изменение местоположения экземпляра, но это не решило проблему.

К счастью, решение состоит в том, чтобы вставлять новые записи в пакетах.Это было блестяще решено ответом в моей предыдущей теме [ Google App Maker для сохранения записей в БД занимает 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'];

... и мы хотим назначить данные о доступности и цене для конкретной строки БД, используя ключ «код продукта».Если код продукта не найден в БД, то мы вставляем новую запись в БД.

Несколько вставок / обновлений в одну строку приводят пользователей Google App Maker в ЕС слишком долго, потому что запрос переходит кСША, даже если экземпляр SQL находится в ЕС.Запуск этого пакета может нарушить сегодняшние ограничения Google App Maker за пределами США.Огромное спасибо за любую помощь, чтобы сделать Google App Maker отличным инструментом для начинающих по всему миру.

Ответы [ 2 ]

2 голосов
/ 04 апреля 2019

С помощью других здесь, в теме, мне удалось сократить время на вставку или обновление записи до 50 мс. Кроме того, я протестировал вставку / обновление 10000 записей в таблицу, содержащую 60 полей. В этом случае скорость составила 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);
}
0 голосов
/ 02 апреля 2019

Эту проблему можно решить, используя надлежащие серверные сценарии, и я настоятельно рекомендую вам прочитать, как серверные сценарии работают в официальной документации .Обратите особое внимание на пример Запрос записей .

Итак, взяв за основу предыдущий пример решения, его можно слегка изменить для достижения ваших потребностей.Вот как это должно выглядеть:

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);

}
...