ニフクラmBaaSお役立ちブログ

スマホアプリ開発にニフクラmBaaS。アプリ開発に役立つ情報をおとどけ!

Google App Scriptを使ってデータストアのバックアップを自動化する

Google App Scriptを使うとmBaaSの定期実行ができるようになります。つまり日次バッチ処理などを実行すれば、毎日手動で行っていた作業が自動で行えるようになります。

今回はデータストアのデータをCSVファイルとしてファイルストアに書き出す処理を自動化してみたいと思います。

処理手順について

全体の処理手順は次の通りです。

  1. Google App ScriptからmBaaSのスクリプト機能を呼び出し
  2. スクリプトにて指定されたクラスのデータをCSVとして保存
  3. 結果をGoogleスプレッドシートに記録

Googleスプレッドシートの内容

まずGoogleスプレッドシートの内容について紹介します。アプリケーションキーや認証に使う情報を載せておきます。データ保存するクラスもスプレッドシートの中に定義しておきます。

Google App Scriptについて

Google App ScriptではまずライブラリとしてNCMBを使います。スクリプトエディタのライブラリにて「1yWnb7GfYsBCR-MZvi6r-TOYv_y-AV4le5P7kaG5B3iZ5VNnSk9Q55pSJ」を登録してください。

次にスクリプトですが、次のようになります。アプリケーションキーやクライアントキー、認証情報などはスプレッドシートから取得します。

function myFunction() {
  // スプレッドシートのオブジェクト
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getActiveSheet();
  
  // 認証情報
  var userName = sheet.getRange("B1").getValue();
  var password = sheet.getRange("D1").getValue();
  
  // アプリケーションキー、クライアントキー
  var application_key = sheet.getRange("B2").getValue();
  var client_key      = sheet.getRange("D2").getValue();
  
  // 処理対象のクラスを取得
  var classes = [];
  classes = sheet.getRange(3, 2, 1, 100).getValues()[0].filter(function(v, i) {
    if (v != "")
      return v;
  });
  
  // 最後の行を取る
  var last_row = 6;
  while (true) {
    if (sheet.getRange(last_row, 1).getValue() == '') {
      break;
    }else{
      last_row++;
    }
  }

後はmBaaSのスクリプト機能を呼び出します。認証情報も渡すことで、権限管理されたデータについても扱えるようにします。処理が成功したら、その内容をスプレッドシートに記録します。

// クラスごとにスクリプト機能を呼び出し
for (var i = 0; i < classes.length; i++) {
  var className = classes[i];
  var ncmb = NCMB.init(application_key, client_key);
  var result = ncmb.Script()
    .query({
      application_key: application_key,
      client_key: client_key,
      className: className,
      userName: userName,
      password: password
    })
    .exec("GET", "csv.js");
    Logger.log(result);
    if (result.filename) {
      // 処理成功
      sheet.getRange(last_row, 1).setValue(className);
      sheet.getRange(last_row, 2).setValue(new Date);
      sheet.getRange(last_row, 3).setValue(result.filename);
      last_row++;
    }
}

mBaaSのスクリプトについて

mBaaSのスクリプトは次のようになります。簡単に言うとデータストアをファイルストアにエクスポートするスクリプトを作成しました | BACKEND AS A SERVICE mbaas BLOGで紹介したスクリプトの返却値を修正しただけです。

このスクリプトの中ではアプリケーションキー、クライアントキーなどは外部から与えられるものとしています。こうすることでスクリプトが公開しやすくなります。

var NCMB = require('ncmb');

module.exports = function(req, res) {
  var application_key = req.query.application_key;
  var client_key      = req.query.client_key;
  var ncmb = new NCMB(application_key, client_key);
  var ClassName       = ncmb.DataStore(req.query.className);
  var d = new Date;
  var filename = req.query.className + "_" + d.getFullYear() + (d.getMonth() + 1) + d.getDate() + ".csv";
  var user = new ncmb.User({userName: req.query.userName, password: req.query.password});
  user.login()
    .then(function(user) {
      var data = [];
      var limit = 1000;
      var loop = function(page) {
        return new Promise(function(resolve, reject) {
          ClassName
            .limit(limit)
            .skip(limit * page)
            .fetchAll()
            .then(function(results) {
              if (Object.keys(results).length == 0) {
                return resolve(true);
              }
              for (var i in results) {
                data.push(results[i]);
              }
              loop(page + 1)
                .then(function() {
                  resolve(true);
                }, function(error) {
                  reject(error);
                })
            })
            .catch(function(error) {
              reject(error);
            })
        });
      }
      loop(0)
        .then(function() {
          csv = [];
          header = [];
          for(var i in data) {
            var ary = Object.keys(data[i]);
            for (var j in ary) {
              if (ary[j] == 'acl') {
                continue;
              }
              if (header.indexOf(ary[j]) < 0) {
                header.push(ary[j]);
              }
            }
          }
          csv = [header.join("\t")];
          for(var i in data) {
            var row = data[i];
            var line = [];
            for (var j in header) {
              if (header[j] == 'acl') {
                continue;
              }
              var val = row[header[j]];
              switch (typeof val) {
              case 'boolean':
              case 'number':
                line.push(val)
                break;
              case 'object':
                switch (val.__type) {
                case 'Date':
                line.push(val.iso);
                  break;
                case 'GeoPoint':
                  line.push(val.latitude + "," + val.longitude);
                  break;
                default:
                  line.push(JSON.stringify(val).replace(/"/g, '""'));
                  break;
                }
                break;
              default:
                try {
                  line.push((val || "").replace(/"/g, '""'))
                }catch(e){
                  console.log(val, typeof val)
                }
              }
            }
            csv.push('"' + line.join('"\t"') + '"');
          }
          // var blob = new Blob(csv.join("\r\n"), {type: "text/csv"});
          buf = new Buffer(csv.join("\r\n"), 'UTF-8');
          ncmb.File.upload(filename, buf)
            .then(function() {
              res.status(200).json({filename: filename});
            })
            .catch(function(error) {
              console.log(error)
            })
        }, function(error) {
          res.status(500).json(error);
        });
      
    })
};

最終的にクラス名+日付でデータをファイルストアに保存します。

Googleスプレッドシートへの記録

処理が成功したらGoogleスプレッドシートにデータが追加されます。こうすることでバックアップ処理が正しく行われているのが確認できるでしょう。


基本的にこの処理は日次バッチ処理を対象としています。Googleスプレッドシートではトリガー処理がありますので、日次処理として定義しておけばサーバレスで運用できるようになります。ぜひご利用ください。