概要
jsforceでサブクエリを含むレコードを取得する際に、子レコードでqueryMoreが発生する際にちょっとハマったので、
取得する方法を紹介したいと思います
サンプルコード(JSforce)
下記のサンプルコードでは以下のような参照関係があるオブジェクトを用いて説明します
また、子レコードは親レコード1件につき2000件以上を取得できるとする
親オブジェクト名はParent__c
子オブジェクト名はChild__c (リレーション名 Child__r)
※当コードは説明用のコードとして作ったものです
効率よく再帰的な処理で実装していませんのでご了承ください
var jsfConn = new jsforce.Connection({ accessToken: '{!$API.Session_Id}' });
jsfConn.query("Select Id, Name, (Select Name from Child__r limit 10000) from Parent__c").run({
// 明示的にautoFetchしない
autoFetch: false
}).then(function(parentRow) {
// autoFetchしないため、1件ずつ取得される
var parentRow = parentRow.records[0];
// 子レコードが200~2000件以上だった場合は、nextRecordsUrlでその続きのレコードを取得する
var nextUrl = parentRow.Child__r.nextRecordsUrl;
// queryMoreにnextRecordsUrlを渡すことで続きが取得できる
jsfConn.queryMore(nextUrl).on("record", function(childRows) {
console.log(childRows);
}).on("end", function() {
console.log("get child rows end");
// 次の親レコードを取得する(再帰的な実装が必要)
jsfConn.queryMore(parentRow.nextRecordsUrl).run({
autoFetch: false
}).then(function(nextParentRow) {
console.log(nextParentRow);
// 子レコードの取得
// ...
});
}).run({
// autoFetchをtrueとすることで、自動で再帰的に取得してくれる
autoFetch: true
});
});
説明
<処理の流れ>
親レコード1 => 親レコード1の子レコード => 親レコード2 => 親レコード2の子レコード => 以降省略・・・
-
親レコードの取得は明示的にautoFetchしない
子レコードを取り切る前に親レコードをすべて取り切ることで、子レコードのnextRecordsUrlが無効になるのを防ぐためjsfConn.query("Select Id, Name, (Select Name from Child__r limit 10000) from Parent__c").run({ autoFetch: false })
-
親レコードの取得はPromiseで取得する
親レコードのnextRecordsUrlを取得するために戻り値をPromiseで受け取る
on("record")イベントではnextRecordsUrlが含まれないjsfConn.query("Select Id, Name, (Select Name from Child__r limit 10000) from Parent__c").run({ autoFetch: false }).then(function(parentRows) {})
-
nextRecordsUrlの件数は200 ~ 2000
nextRecordsUrlが結果に含まれる条件としては、取得しようとしたレコード数が200~2000以上の時
取得対象項目の型に応じて取得可能なレコード数が変わります
例えば、ロングテキスト型を含む場合は、1度に取得できるレコード数は200件になります
リファレンス
https://jsforce.github.io/document/#query
https://developer.salesforce.com/docs/atlas.en-us.ajax.meta/ajax/sforce_api_ajax_more_samples.htm?search_text=queryMore