【営業向け】SalesforceのフロービルダーでToo many SOQL queries: 101に引っかからないように工夫したこと


この記事について

Salesforceを利用している組織において、私もそうなのですが、営業担当者がカスタマイズを担当していることがあるかと思います。Salesforceの豊富な機能の中で『フロー』という機能がありますが、Too many SOQL queries: 101というエラーに何度も遭遇してしまいました。色々調べている中で、エラーを回避できるプラクティスを残している記事があまり多くないなと思いましたし、自分なりの解決方法が分かってきましたので、記事にしました。少しでも同じ苦しみを感じている人の助けになればと思います。

ちなみにフロービルダーが何かを理解している方向けの記事になります。

Too many SOQL queries: 101とは?

Salesforce社の公式のヘルプによると、

コンテキストで合計 100 個までの SOQL クエリを実行することができるガバナ制限に達した場合に、以下のエラーが表示されます。

​「System.LimitException: Too many SOQL queries: 101」

とのことです。営業担当者がこれを見てすぐに理解はできないと思います。
ほとんどの営業担当者が、『ああ、ガバナ制限でクエリがコンテキストでエラーが100個ね(震え声)』となると思います。

要するに、『データベースへのアクセスを何度も何度も一度の処理の中でやらないでくれ!』という理解があれば十分です。

問題の処理

例えば以下のような設定を行ったとします。

解説をすると、
1:全商談情報を配列で取得
2:1で取得した配列をループ処理する
3:ループ処理中に商談に紐づく取引先責任者の所有者をupdateする
となります。

これの何が悪いかというと、ループ中に何度もUpdateを呼んでしまっているので、パフォーマンスがめちゃめちゃ悪くなります。
以前GASの記事で書いていたようなことをSalesforceでもやってしまっているということです。
【営業向け】マクロの実行速度を100倍ぐらい早くできたので忘備録

GAS風に説明すると、SalesforceにもID付きのオブジェクトを配列に格納し、updateをかけてあげると一括で更新をかけてくれるメソッドがありますので、これを使ってあげれば何度もデータベースへアクセスをしなくて済み、制限にもかからなくなります。

具体的な回避の方法

具体的な回避方法としましては、ループの外で一括で更新をかけ、SOQLの発行数を少なくし、エラーを回避します。

上記の設定を解説いたしますと、
1: 商談情報を配列(Salesforceではコレクション変数と呼びます)で取得
2: コレクション変数をループ処理
3: 新しく用意した変数にループ処理で取り出したidを格納
4: コレクション変数に3のオブジェクトを格納
5: 一括で更新の処理をかける
となります。

それぞれの手順を3から説明します。

新しく用意した変数にループ処理で取り出したidを格納

新しく要素を追加をクリックするとメニューが立ち上がるので『割り当て』を選択。

割り当ての編集画面が表示されるので、『新規リソース』を選択。

リソース種別を聞かれるので、変数を選択。

変数の名前などを聞かれるので、これは適当に分かりやすい名前を設定し、データ型は『レコード』、オブジェクトは今回に関しては『取引先責任者』を選択。

新しく用意したnew_contract_valiableという変数に、idと所有者をセット。演算子は『次の文字列と一致する』を選択してください。


演算子に『次の文字列と一致する』を選択することに、若干の違和感を感じるかと思いますが、GASで説明すると以下のようなことをしているとイメージしていただければと思います。

gas.js
var getAllOpportunity = getOppRecords();
//商談のレコードを取得するメソッドが定義されていえると考えてください

var new_contact_valiable = new Contact();
//Contactオブジェクトが定義されていると考えてください

getAllOpportunity.forEach(function(roopOppList)){
   new_contact_valiable.Id = roopOppList.OppRepresentative.id;
   new_contact_valiable.OwnerId = roopOppList.OwnerId;
}

コレクション変数に3のオブジェクトを格納

手順3と同じように、新しくリソースを用意します。

今回用意する変数はコレクション変数になりますので、『複数の値を許可』をチェック。これをチェックすることで空のコレクション変数を用意することができます。

最後に、3で用意したnew_contact_valiableを用意したコレクション変数に『追加』します。

コードで表現すると以下のようなイメージです。

gas.js
var getAllOpportunity = getOppRecords();
//商談のレコードを取得するメソッドが定義されていえると考えてください

var new_contact_valiable = new Contact();
//Contactオブジェクトが定義されていると考えてください

var collection_valiable_for_update = [];
//空のコレクション変数を用意

getAllOpportunity.forEach(function(roopOppList)){
   new_contact_valiable.Id = roopOppList.OppRepresentative.id;
   new_contact_valiable.OwnerId = roopOppList.OwnerId;
   collection_valiable_for_update.push(new_contact_valiable);
}

一括で更新の処理をかける

最後に、ループの外で更新の処理をします。『レコードまたはレコードコレクションからのID及びすべての項目値を使用』をチェックし、新しく用意をしたcollection_valiable_for_updateというコレクション変数を指定してあげれば、一括で特定のレコードを更新しに行くことができます。

まとめ

手順だけざっと説明しましたが、やっていることは以下のようなイメージになります。少し複雑ですが、慣れてくるとフローを利用して様々な自動化処理を実装することができるようになります。レコードの更新だけでなく、メールの送信や、chatterの投稿などなど、非常に強力な自動処理をすることもできます。

時代はノーコードですね。もはやコーディングをすること自体が古い時代になるのかもしれません。あらゆるSaaSでノーコードでカスタマイズする時代が来る気がしています。そうなったときに、非エンジニアでもデータ構造とアルゴリズムをきちんと理解していることはとても大事な要素に思います。