(GAS)PUT操作でUPSERT処理をしたい

何を実現したいのかを書きましょう

★確認したいこと:PUT処理にはUPSERTの機能があるのか確認したい
・kintoneアプリへのデータ更新をGASでプログラムを組んでPUT操作を実行したが、updateKeyが一致しない場合にはエラーが発生し新規登録できない状態
・IF文で対象データ単位でレコードが存在してる場合にはPUT、レコードが存在しない場合にはPOST処理をするようなプログラムは組んだが、その場合、1000~1万件レベルになると処理時間が掛かりすぎて完了しないため、PUT操作により一括の処理100件単位で繰り返し実行し処理時間の短縮を図りたい(CSVでの読込操作と同じように100件単位で新規登録/更新処理をしたい)
・PUT操作には、updateKeyが一致しない場合には新規レコード登録されると思っていたが、エラーとなってしまうため、そもそもUPSERT処理ができる機能があるのかを確認したい

どなたか、ご回答頂けると幸いです。

発生した問題やエラーメッセージを具体的に書きましょう

★問題点:GASで実行すると以下のエラーがでてくる
・エラー内容→"code":“GAIA_RE20”,“message”:“「updateKey」に指定した条件にあてはまるレコードが見つかりません。”

★検証内容:以下のことは確認しているので、updateKeyのフィールドコード指定問題無し、アプリへの重複禁止設定は問題無し、'X-Cybozu-Authorization’指定での読込書き込み権限は問題無し、という状況
・このプログラムで一致したレコードがあれば更新されることは確認済み
・MethodをPOSTに変更し、データ構成をupdateKeyがない状態に変更して実行すると新規レコード登録されることを確認済み

実行したコードをコピー&ペーストしましょう

--------------データ構造例-------------

   for(j=0;j<upData_length;j++){
       var record ={
        'updateKey': {
          'field': 'unique_key',
          'value': data[i][0]
        },
        "record": {
          'workerno'                : {"value" :data[i][1]},
          'projectNo'               : {"value" :data[i][2]}
        }
       };      

    records.push(record);
   }

    var res = updateKintone(method,records,appId);

-----------実行関数---------

  var requestData = {
    'app': appId,
    'records': records
  };

  var options = {
    'method': method,
    'headers': {
      'Content-Type':'application/json',
      'X-Cybozu-Authorization': authorization,
    },
    'payload': JSON.stringify(requestData),
     "muteHttpExceptions": true
  };

  var url = api_url + '/k/v1/records.json';

  var response = UrlFetchApp.fetch(url, options);
  var res = response.getContentText();
  return res;


榊谷
SAKAKIさん

こんにちは、すでに失敗時の ““muteHttpExceptions”: true” を指定しているのですね。
恐らく

var response = UrlFetchApp.fetch(url, options);

の変数 responseにステータスコード等がオブジェクトとして格納されているはずなので、軽く私が見た感じですと以下のようにすればいけないかな?と考えております!

var response = UrlFetchApp.fetch(url, options);

//↓ステータスコード200以外だとエラーとみなすため。
if(response.getResponseCode() !=  '200'){
      //ここにPUTが失敗した時の処理を書く。
}

一度試していただいてまたフィードバックいただけると幸いでございます!

ご確認頂きまして、誠にありがとうございます。

失敗したデータ群に対して、IF文で条件分岐して、PUT処理とPOST処理をさらに条件分岐しながら1データ単位で新規登録または更新処理をしていくというフローもできるのですが、やはり1000~1万単位のデータを一括更新するとなると処理時間オーバーで完了しなくなるんですよね。

もう少し詳しく書くと、以下のように100単位でデータを区切って、まとめてPUT処理をするという流れです。この100単位のデータ群で1つでもエラーが発生すると、ご提案頂いた形ですとIF文の中で100データをデータ1つ単位に区切って、レコードがあればPUT、レコードがなければPOST処理という処理になりますので、処理時間が非常に掛かってしまいます。

ですので、PUT操作のみでまとめてUpsert処理ができる方法があればなと思った次第です。

ご回答ありがとうございます。

  //データ単位
  const unit=100;

  //アプリ登録データの格納
  var data = sheetPost2.getRange(2,6,d_length-1,3).getValues();
  
  const countR = data.length/unit //100で割る繰り返し数
 
  for (i=0;i<countR;i++){
    var records = [];
 
    if(countR-i<1){
      upData_length = data.length- i*unit;
    }
   var upData = sheetPost2.getRange(2+i*unit,6,upData_length,3).getValues();

   for(j=0;j<upData_length;j++){
       var record ={
        'updateKey': {
          'field': 'unique_key',
          'value': data[i][0]
        },
        "record": {
          'workerno'                : {"value" :data[i][1]},
          'projectNo'               : {"value" :data[i][2]}
        }
       };      

    records.push(record);
   }

    var res = updateKintone(method,records,appId);
}

榊谷SAKAKIさん
ご返事ありがとうございます。
されたい事として存在するレコードに対してはまとめてPUTしたい、無いレコードに対してはまとめてPOSTされたいということですかね??
恐らくKintoneのデータを全件取得した上でそれぞれ配列を作成して処理を行う必要があるかなと考えております。
現段階で試されてエラーが出ていることはupdatekeyがないため更新できないとなっているので、そこは例外的に処理をするのは厳しいかなと考えております。

また、GASなのですが、実は私あまりよくわかっていないのですが、外部のライブラリなど使用はできませんか?
できるのであれば、KintoneRestApiClientを使用すればあるGETもPUTもPOSTも一括で処理できる関数が用意されておりますので…
参考URL:https://cybozudev.zendesk.com/hc/ja/articles/900000566086-目指せ-JavaScriptカスタマイズ中級者-4-kintone-REST-API-Client編-?_ga=2.35933479.649166314.1692574618-923425052.1689224001

恐らく 榊谷SAKAKIさんの求められている回答は違いますが一例としてお伝えさせて頂きました。

Yuki_Minamitaniさん

ご返信ありがとうございます。
なるほど、KintoneRestApiClientを試してみます。

ところでご提案頂いた、全件取得しての配列再作成等も事前に試していたのですが、扱っているレコード数が非常に多すぎて、その処理も難しいという状況でしたので、一括処理できる方法を模索しておりました。

ご提案頂いた内容を検証してみます。

「いいね!」 1

榊谷SAKAKIさん

こちらこそご返事ありがとうございます、恐らく
kintoneの対象レコードを全件取得してくる

すでにあるものかfor()やforEach()などで繰り返して取得してきたものに対して、新規登録なのか更新するレコードなのか判別して配列を作成する

kintoneに対して登録及び更新処理は長いので、非同期処理で流してしまう

というような流れになるんじゃないかなと簡略的に考えてみました…

また、何かフィードバック等ございましたら、私も気になりますので教えてくださったら幸いでございます!

「いいね!」 2

そもそもUPSERT処理ができる機能があるのかを確認したい

kintoneのAPIには1つのエンドポイントでUPSERTできるものはないです。なので @y_minamitani9534 さんが書かれている方法になります。

「いいね!」 2

ご回答ありがとうございます。
エンドポイントでUPSERTできるものがないということが確認できましたので、すっきりしました。

ちなみですが、Chat-GPTで以下の質問をすると、
★回答の一部→updateKey が一致しないと新規レコードが作成されるというのは正しい動作です。
という回答がでてくるんですよね。
それでPUT操作でUPSERTできるものだと誤解していました。

(質問内容)
kintoneアプリへのデータ更新をGASでPUT操作により実行したが、updateKeyで一致しない場合に新規登録できない。

「いいね!」 1

ちなみですが、Chat-GPTで以下の質問をすると、
★回答の一部→updateKey が一致しないと新規レコードが作成されるというのは正しい動作です。
という回答がでてくるんですよね。

あるあるですねー。
ほんまかいな?と思ったら私は「エビデンスとなる公式ドキュメントの参照先を示してください」などと書いて聞いたりしてます。

「いいね!」 2

そのような質問方法は気づかなったですね!
chat-GPTの質問の仕方、参考になります。
ありがとうございます。

このトピックはベストアンサーに選ばれた返信から 3 日が経過したので自動的にクローズされました。新たに返信することはできません。