Dynamics 365(Dynamics CRM)Web API レコード取得編 Part.Ⅴ
みなさん、ちゃーっす!
夏バテで『ピノ チョコアソート』を食べ倒してる Harada です。
アーモンドが一番好きです!(*`・へ・´*)ドヤァ
さて、今回はご要望頂きましたレコード取得時のページングとFetchXML の実行とページングについて書かせてもらおうと思います。
Dynamics 365 レコード取得 ページング
Web API でレコードを取得する場合、ページングをしない場合は最大5,000件という制限があります。取得するフィールド数や処理する側のスペックにもよりますが、一度に5,000件取得するとクライアント側の処理に時間がかかり、パフォーマンスの問題となることがあります。
そこで、ページングが必要となります。ページングとは、5,000件のデータを1,000件ずつ5回取得することを言います。
なんとなくページングについてご理解いただけましたか?理解できた方も理解できなかった方も下記のサンプルを確認してください(笑)
var apiUrl = "https://<ORG>.crm7.dynamics.com/api/data/v8.2/incidents";
var s = '$select=casetypecode,checkemail,_customerid_value,description,';
s += 'exchangerate,followupby,influencescore,numberofchildincidents,';
s += '_owninguser_value,statecode,statuscode,ticketnumber,title,versionnumber';
// 実行
execute(encodeURI(apiUrl + '?' + s));function execute(requestUrl) {
var xhr = new XMLHttpRequest();
xhr.open("GET", requestUrl, true);
xhr.setRequestHeader('Accept', 'application/json');
xhr.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
xhr.setRequestHeader('OData-MaxVersion', '4.0');
xhr.setRequestHeader('OData-Version', '4.0');
// 1ページあたりのレコード数を指定
xhr.setRequestHeader('Prefer', 'odata.include-annotations="*",odata.maxpagesize=10');
xhr.onreadystatechange = function () {
if (this.readyState == 4) {
if (this.status == 200) {
console.log(this.response);
var data = JSON.parse(this.response);
// さらにレコードがある場合に再帰
if (data["@odata.nextLink"])
execute(data["@odata.nextLink"]);
} else {
var error = JSON.parse(this.response).error;
Xrm.Utility.alertDialog(error.message, function () { });
}
}
};
xhr.send();
}
さて、以前までの分と何が違うのでしょうか・・・簡単に説明します。
- 1行目 ~ 4行目
- レコード取得のURLを作成しています。ここは、以前と変わりないですね。
- 6行目
- この行の下で定義している function を呼び出しています。
- 16行目
- 1度に取得するレコード数を指定しています。ここでは1度のリクエストで10件返すように指定しています。
- 23行目、24行目
- さらにレコードがあるかどうかは、戻ってきたデータ『@odata.nextLink』にURLが入っているためこちらで再度リクエストします。
意外と簡単だと思いませんか?ただ、ページ番号を指定して取得することが簡単にできそうにないという点が残念です。
Dynamics 365 レコード取得 FetchXMLの実行
つづいて、以前簡単に触れたFetchXMLの実行です。FetchXMLなので、集計にしようかと思ったのですが、ページングのほうが難しそうだったので、ここではFetchXMLでのページングのサンプルを記載します。それではご覧あれ~!
var apiUrl = "https://<ORG>.crm7.dynamics.com/api/data/v8.2/incidents";
var page = 1; // ページを指定
var count = 10; // 1ページあたりのレコード数を指定
// fetch エレメント の子エレメントを定義
var xml = '<entity name="incident" ><attribute name="ticketnumber" />';
xml += '<attribute name="title" /><attribute name="exchangerate" />';
xml += '<attribute name="checkemail" /><attribute name="casetypecode" />';
xml += '<attribute name="statuscode" /><attribute name="versionnumber" />';
xml += '<attribute name="owninguser" /><attribute name="customerid" />';
xml += '<attribute name="statecode" /><attribute name="numberofchildincidents" />';
xml += '<attribute name="followupby" /><attribute name="influencescore" />';
xml += '<attribute name="description" /></entity>';
// 実行
executeFetchXml(apiUrl, xml, page, count);function executeFetchXml(apiUrl, fetch, page, count, pagingCookie) {
// fetchXml を作成
var fetchXml = 'fetchXml=<fetch';
fetchXml += ' page="' + page + '"';
fetchXml += ' count="' + count + '"';
if (pagingCookie) {
fetchXml += " " + escape(pagingCookie);
}
fetchXml += '>' + fetch + '</fetch>';
var xhr = new XMLHttpRequest();
xhr.open("GET", encodeURI(apiUrl + "?" + fetchXml), true);
xhr.setRequestHeader('Accept', 'application/json');
xhr.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
xhr.setRequestHeader('OData-MaxVersion', '4.0');
xhr.setRequestHeader('OData-Version', '4.0');
// ページング用の注釈を指定。
xhr.setRequestHeader('Prefer', 'odata.include-annotations="*"');
xhr.onreadystatechange = function () {
if (this.readyState == 4) {
if (this.status == 200) {
console.log(this.response);
var data = JSON.parse(this.response);
// さらにレコードがある場合に再帰
var cookies = data["@Microsoft.Dynamics.CRM.fetchxmlpagingcookie"];
if (cookies) {
page++;
pagingCookie = getPagingCookie(cookies);
executeFetchXml(apiUrl, fetch, page, count, pagingCookie);
}
} else {
var error = JSON.parse(this.response).error;
Xrm.Utility.alertDialog(error.message, function () { });
}
}
};
xhr.send();
}
function getPagingCookie(pagingCookies) {
var div = document.createElement('div');
div.innerHTML = pagingCookies;
var pageNumber = div.firstChild.attributes.pagenumber.value;
var pagingcookie = div.firstChild.attributes.pagingcookie.value;
pagingcookie = unescape(unescape(pagingcookie));
pagingcookie = pagingcookie.replace(/</g,'<').replace(/>/g,'>');
pagingcookie = pagingcookie.replace(/"/g,''').replace(/'/g,'&'+'quot;');
return "paging-cookie='" + pagingcookie + "'";
}
なかなか厄介でした。。。ページングをするには<fetch>エレメントを変更していく必要があるので、ややこしくなりますね。それでは説明です。
- 1行目
- Web API のURLなので説明は不要ですね。
- 2行目
- 取得するページ番号を指定しています。
- 3行目
- 取得するレコード数を指定しています。
- 5行目 ~ 12行目
- FetchXMLの<entity>以下を指定しています。
- 18行目 ~ 24行目
- <fetch>エレメントにページングの設定を行っています。
- 33行目
- ページングに使用する『@Microsoft.Dynamics.CRM.fetchxmlpagingcookie』を取得するために注釈の指定が必要です。(ちょっと調べたのですが"*"でなく、単体で取得する注釈がわかりませんでした。。)
- 41行目 ~ 43行目
- さらにレコードがあるかどうかは、戻ってきたデータ『@Microsoft.Dynamics.CRM.fetchxmlpagingcookie』があるかどうかで判定し、再帰で呼び出すためにページ番号、クッキーを再設定しています。
- 55行目
- 『getPagingCookie』では『@Microsoft.Dynamics.CRM.fetchxmlpagingcookie』で取得した文字列からpagingcookie属性の値の取得を行っています。『@Microsoft.Dynamics.CRM.fetchxmlpagingcookie』には下記のような文字列が設定されています。
<cookie pagenumber="2" pagingcookie="%253ccookie%2520page%253d%25223%2522%253e%253cincidentid%2520last%253d%2522%257bE384A5B4-498A-E711-8118-C4346BC53068%257d%2522%2520first%253d%2522%257bD184A5B4-498A-E711-8118-C4346BC53068%257d%2522%2520%252f%253e%253c%252fcookie%253e" istracking="False" />
FetchXMLでのページングはこんな感じです。いかがですか?参考になりますでしょうか。私は疲れました(笑)
今回、はじめてFetchXMLでのページングを実装したのですが、『@Microsoft.Dynamics.CRM.fetchxmlpagingcookie』で返される cookie の中に pagenumber があるのでその値をインクリメントすればいいと思ってやっていたんですが・・・正しい値が返ってこず苦戦しました(笑)
このように実装してみないとわからないことがあるのが Dynamics 365 の醍醐味ですね。
次回は・・・・って何も考えてなかったw 何かしら有益な情報をかけるようにネタを探しておきますm(_ _)m
※ 記事の内容は個人発信の参考情報です。記事内容のご利用は、ご自身の判断でお願いします。