バッチ処理 | Graph API の概念

Azure AD Graph API では、サーバーへのラウンドトリップを減らすためエンティティでバッチ処理を実行できます。 要求をバッチ処理すると、ネットワークのオーバーヘッドが減り、操作をより迅速に完了できます。

重要

Azure AD Graph API の機能は、統合 API の Microsoft Graph からも使用できます。Microsoft Graph には、Outlook、OneDrive、OneNote、Planner、Office Grap など他の Microsoft サービスの API も含まれており、これらはすべて単一のアクセス トークンを使用して単一のエンドポイントからアクセスします。 バッチ処理は現在、Microsoft Graph でサポートされていません。この機能には、Azure AD Graph API を使用する必要があります。

OData バッチ要求での Graph API のサポート

エンティティのバッチ処理のセマンティクスは、「OData 3.0 バッチ処理の仕様」で定義されています。 OData 仕様では、バッチ要求に関する次の概念が定義されています。

  • クエリとは、1 つのクエリまたは関数の呼び出しです。
  • 変更セットとは、1 つ以上の挿入、更新、または削除操作、アクション呼び出しまたはサービス呼び出しのグループです。
  • バッチは操作のコンテナーであり、1 つ以上の変更セットおよびクエリ操作が含まれます。

Graph API は、OData 仕様で定義される機能のサブセットをサポートしています。

  • 1 つのバッチには、最大で 5 つのクエリと変更セットの両方または一方を組み合わせて含めることができます。
  • 変更セットには、最大で 1 つのソース オブジェクトの変更、および最大で 20 のリンクの追加とリンクの削除操作を組み合わせて含めることができます。 変更セット内のすべての操作は、1 つのソース エンティティにある必要があります。

Graph API のバッチ要求

次のセクションでは、バッチ要求を作成する方法とバッチ応答を解釈する方法について説明し、それぞれの例を示します。

バッチ要求の構文

バッチ要求を実行するには、要求 URI で $batch オプションを指定します。 たとえば、

https://graph.windows.net/contoso.onmicrosoft.com/$batch?api-version=1.6

バッチ要求は、1 つの POST ディレクティブでサーバーに送信されます。

このペイロードは、バッチとその構成クエリと変更セットを含むマルチパート MIME メッセージです。 このペイロードには次の 2 種類の MIME 境界が含まれます。

  • バッチ内の各クエリと変更セットを分割するバッチ境界。
  • 変更セット内の個々の操作を分割する変更セット境界。

変更セット内の個々の要求は、その操作が単独で呼び出されたときに作成される要求と同じです。 たとえば、

  • 変更セットに含まれる各操作に対してペイロード形式 (JSON または ATOM) を指定するには、適切な Content-Type と必要に応じて Accept ヘッダーを含めます。
  • エンティティの作成時に応答のコンテンツ エコーを抑制するには、変更セットに含まれる各挿入操作に return-no-content 値と共に Prefer ヘッダーを指定します。

要求例

次の例で、5 つの項目を含むバッチ要求を示します。

  1. ユーザー、testuser@contoso.onmicrosoft.com を作成する変更セット (POST)。 この操作には、返される新しく作成したユーザーを抑制する、Prefer: response-no-content header ヘッダーが含まれます。
  2. 新しいユーザーの部門やジョブ タイトル プロパティを更新し (PATCH)、そのマネージャー ナビゲーション プロパティを設定する (PUT) 変更セット。
  3. 新しいユーザーのマネージャーに対するクエリ (GET)。
  4. 新しいユーザーを削除する変更セット (DELETE)。
  5. ユーザーに対するクエリ (GET)。 この操作は、前の手順でユーザーが削除されたために失敗します。
POST https://graph.windows.net/contoso.onmicrosoft.com/$batch?api-version=1.5 HTTP/1.1
Authorization: Bearer ey … jQA
Content-Type: multipart/mixed; boundary=batch_36522ad7-fc75-4b56-8c71-56071383e77b 
Host: graph.windows.net
Content-Length: 2961

--batch_36522ad7-fc75-4b56-8c71-56071383e77b 
Content-Type: multipart/mixed; boundary=changeset_77162fcd-b8da-41ac-a9f8-9357efbbd620 
Content-Length: 631       

--changeset_77162fcd-b8da-41ac-a9f8-9357efbbd620 
Content-Type: application/http 
Content-Transfer-Encoding: binary 

POST /contoso.onmicrosoft.com/users?api-version=1.5 HTTP/1.1
Content-Type: application/json
Accept: application/json
Content-Length: 256
Prefer: return-no-content
Host: graph.windows.net

{
    "accountEnabled": true,
    "displayName": "Test User",
    "mailNickname": "testuser",
    "passwordProfile": { "password" : "Test1234", "forceChangePasswordNextLogin": false },
    "userPrincipalName": "testuser@contoso.onmicrosoft.com"
}

--changeset_77162fcd-b8da-41ac-a9f8-9357efbbd620----batch_36522ad7-fc75-4b56-8c71-56071383e77b 
Content-Type: multipart/mixed; boundary=changeset_4b2cbfb7-011d-4edb-8bbf-e044f9830aaf 
Content-Length: 909

--changeset_4b2cbfb7-011d-4edb-8bbf-e044f9830aaf 
Content-Type: application/http 
Content-Transfer-Encoding: binary 

PATCH /contoso.onmicrosoft.com/users/testuser@contoso.onmicrosoft.com?api-version=1.5 HTTP/1.1
Content-Type: application/json
Accept: application/json
Content-Length: 72
Host: graph.windows.net

{
    "department": "Engineering",
    "jobTitle": "Test Engineer"
}

--changeset_4b2cbfb7-011d-4edb-8bbf-e044f9830aaf 
Content-Type: application/http 
Content-Transfer-Encoding: binary 

PUT /contoso.onmicrosoft.com/users/testuser@contoso.onmicrosoft.com/$links/manager?api-version=1.5 HTTP/1.1
Content-Type: application/json
Accept: application/json
Content-Length: 112
Host: graph.windows.net

{
  "url":"https://graph.windows.net/contoso.onmicrosoft.com/users/a71e4d1c-ce99-40dc-8d4b-390eac63e039"
}

--changeset_4b2cbfb7-011d-4edb-8bbf-e044f9830aaf----batch_36522ad7-fc75-4b56-8c71-56071383e77b 
Content-Type: application/http 
Content-Transfer-Encoding:binary

GET /contoso.onmicrosoft.com/users/testuser@contoso.onmicrosoft.com/$links/manager?api-version=1.5 HTTP/1.1
Accept: application/json
Host: graph.windows.net

--batch_36522ad7-fc75-4b56-8c71-56071383e77b 
Content-Type: multipart/mixed; boundary=changeset_9a0b5878-0f4a-4f57-91c5-9792cdd5ef20 
Content-Length: 331       

--changeset_9a0b5878-0f4a-4f57-91c5-9792cdd5ef20 
Content-Type: application/http 
Content-Transfer-Encoding: binary 

DELETE /contoso.onmicrosoft.com/users/testuser@contoso.onmicrosoft.com?api-version=1.5 HTTP/1.1
Accept: application/json
Host: graph.windows.net


--changeset_9a0b5878-0f4a-4f57-91c5-9792cdd5ef20----batch_36522ad7-fc75-4b56-8c71-56071383e77b 
Content-Type: application/http 
Content-Transfer-Encoding:binary

GET /contoso.onmicrosoft.com/users/testuser@contoso.onmicrosoft.com?api-version=1.5 HTTP/1.1
Accept: application/json
Host: graph.windows.net

--batch_36522ad7-fc75-4b56-8c71-56071383e77b--

バッチ応答の構文

応答では、バッチ要求の全体的なステータス コードと、バッチに含まれる各項目の個別のステータス コードと結果のフラグメントが返されます。 応答は、バッチ境界と変更セット境界が含まれるマルチパート MIME メッセージです。

バッチ要求が正しく認証され Graph API によって正常に受信される場合、バッチに含まれる操作のいずれかが失敗しても、バッチ要求はステータス コード 202 Accepted を返します。 バッチ要求自体が失敗する場合は、バッチに含まれる全操作の実行前に失敗します。 たとえば、認証エラーによってバッチ要求が失敗することがあります。その場合、ステータス コードにそのエラーが示されます。

クエリ項目の応答フラグメントには、操作の成功または失敗を示す 1 つのステータス コードと適切な応答本文が含まれます。

変更セット内の操作はアトミックに処理されます。つまり、変更セット内のすべての操作が成功するか、変更セット全体が失敗します。 Graph API は、1 つの操作が失敗するまで変更セット内の操作の処理を継続します。 操作が失敗した場合、変更セット内のそれ以前の操作はすべてロールバックされます。

変更セット内のすべての操作が正常に処理された場合、変更セット内の各操作のステータス コード (および応答本文) が変更セットの応答に表示されます。 変更セットの操作が失敗する場合、その変更セットには 1 つのステータス コードのみが返されます。 これは、失敗した操作が返すステータス コード (および応答本文) です。たとえば、400 Bad Request または 404 Not Found

応答例

次の例は、前に示した要求例で送信したバッチ操作の応答を示しています。 バッチ要求自体のステータスは、202 Accepted に設定されます。 これは、バッチ自体には問題がないことを示します。 バッチ内の各項目の応答は、batchresponse 境界識別子によって区切られ、変更セット内の操作に対する各応答は、changesetresponse 境界識別子で区切られます。

次に、各バッチ項目の応答フラグメントを示します。

  1. 新しいユーザーを作成する POST 要求のステータスは、204 No Content に設定されます。 これは、要求で Prefer ヘッダーが return-no-content に設定されているためです。 これは、ユーザーが正常に作成されたことを示します。
  2. 2 番目のバッチ項目には、2 つ 204 No Content* 応答が含まれます。1 つは、ユーザー オブジェクトの更新用 (PATCH) で、もう 1 つは変更セット内のマネージャーのリンクの設定用 (PUT) です。 これは、両操作が成功したことを示します。
  3. ユーザーのマネージャーを読み取る要求への応答では、マネージャーへのリンクと 200 OK のステータスが返されます。
  4. ユーザー削除の試行ステータスは、204 No Content です。 これは、操作が成功したことを示します
  5. 削除されたユーザーの読み取り試行のステータスは 404 Not Found で、応答には、ユーザー (リソース) が見つからなかったことを示すコードとメッセージが含まれています。
HTTP/1.1 202 Accepted
Cache-Control: no-cache
Pragma: no-cache
Content-Type: multipart/mixed; boundary=batchresponse_1eb70252-25d2-466c-9a1d-7a3f45378b06
Expires: -1
Server: Microsoft-IIS/8.5
ocp-aad-diagnostics-server-name: Nv0YIi2YUldDWu0YPQAXsYwXQ4ttyr7ded6Waf8xyCc=
request-id: 2f7d2f81-3441-4c2a-b494-25cd1d6ce624
client-request-id: f40c00af-3e1f-4198-9261-386f0e3aecc6
x-ms-gateway-rewrite: false
x-ms-dirapi-data-contract-version: 1.5
ocp-aad-session-key: cdhenl3mgHuI3vaRRIQ14uXdwRLUqirNpDXjJP42EzUEvqhhn2NFr22ulR4PsqrM1UD_eSUDItt7J9kUQhNvTT_48q90coHHt2RutCIgPNg.lD81Z0iS2SaHbqkfAaDvbbigoX7ak7rfiUGFby0LOIE
X-Content-Type-Options: nosniff
DataServiceVersion: 1.0;
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
X-Powered-By: ASP.NET
Date: Tue, 20 Jan 2015 23:21:15 GMT
Content-Length: 3065

--batchresponse_1eb70252-25d2-466c-9a1d-7a3f45378b06
Content-Type: multipart/mixed; boundary=changesetresponse_8a63ce5e-ed31-4de6-bc90-9d3ff31debbb--changesetresponse_8a63ce5e-ed31-4de6-bc90-9d3ff31debbb
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 204 No Content
X-Content-Type-Options: nosniff
Cache-Control: no-cache
Preference-Applied: return-no-content
DataServiceVersion: 3.0;
Location: https://graph.windows.net/contoso.onmicrosoft.com/directoryObjects/6a287a96-ede9-44d2-b685-d6fc03a124c5/Microsoft.DirectoryServices.User
DataServiceId: https://graph.windows.net/contoso.onmicrosoft.com/directoryObjects/6a287a96-ede9-44d2-b685-d6fc03a124c5


--changesetresponse_8a63ce5e-ed31-4de6-bc90-9d3ff31debbb----batchresponse_1eb70252-25d2-466c-9a1d-7a3f45378b06
Content-Type: multipart/mixed; boundary=changesetresponse_11ba5cf0-9fba-4995-9f15-bd5c9981cdd6--changesetresponse_11ba5cf0-9fba-4995-9f15-bd5c9981cdd6
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 204 No Content
X-Content-Type-Options: nosniff
Cache-Control: no-cache
DataServiceVersion: 1.0;


--changesetresponse_11ba5cf0-9fba-4995-9f15-bd5c9981cdd6
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 204 No Content
X-Content-Type-Options: nosniff
Cache-Control: no-cache
DataServiceVersion: 1.0;


--changesetresponse_11ba5cf0-9fba-4995-9f15-bd5c9981cdd6----batchresponse_1eb70252-25d2-466c-9a1d-7a3f45378b06
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 200 OK
DataServiceVersion: 3.0;
Content-Type: application/json;odata=minimalmetadata;streaming=true;charset=utf-8
X-Content-Type-Options: nosniff
Cache-Control: no-cache

{
  "odata.metadata":"https://graph.windows.net/contoso.onmicrosoft.com/$metadata#directoryObjects/$links/manager",
  "url":"https://graph.windows.net/contoso.onmicrosoft.com/directoryObjects/a71e4d1c-ce99-40dc-8d4b-390eac63e039/Microsoft.DirectoryServices.User"
}
--batchresponse_1eb70252-25d2-466c-9a1d-7a3f45378b06
Content-Type: multipart/mixed; boundary=changesetresponse_bb215a84-f91e-4486-a771-ba2cc5d429d1--changesetresponse_bb215a84-f91e-4486-a771-ba2cc5d429d1
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 204 No Content
X-Content-Type-Options: nosniff
Cache-Control: no-cache
DataServiceVersion: 1.0;


--changesetresponse_bb215a84-f91e-4486-a771-ba2cc5d429d1----batchresponse_1eb70252-25d2-466c-9a1d-7a3f45378b06
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 404 Not Found
X-Content-Type-Options: nosniff
Cache-Control: no-cache
DataServiceVersion: 3.0;
Content-Type: application/json;odata=minimalmetadata;streaming=true;charset=utf-8

{
  "odata.error":
    {
      "code":"Request_ResourceNotFound",
      "message":
        {
          "lang":"en",
          "value":"Resource 'testuser@contoso.onmicrosoft.com' does not exist or one of its queried reference-property objects are not present."
        }
    }
}
--batchresponse_1eb70252-25d2-466c-9a1d-7a3f45378b06--

エラー応答の例

前述のとおり、Graph API がバッチを許可できる (つまり、バッチ要求の形式が適切で、認証エラーなどのエラーがない) 場合、202 Accepted のエラー コードが返されます。 これ以外の場合は、Graph API は適切なエラーを返し、バッチを処理しません。 バッチ内の個々の項目が失敗する場合、その項目の応答フラグメントにはそのエラーを示すステータス コードおよび応答本文が格納されます。 変更セット内の操作が失敗した場合、変更セット全体に対し 1 つの応答フラグメントが返され、そのフラグメントには、失敗した操作に関連するステータス コードおよび応答本文が含まれます。

次の例では、操作の 1 つが失敗した変更セットを含むバッチ要求からの応答を示しています。 バッチ応答は、202 Accepted のステータス コードを返すことに注意してください。 変更セットに対し返されたステータス コードは、404 Not Found のステータスで操作が失敗したことを示します。 失敗した操作について、応答本文に追加のエラー情報が含まれています。 code 要素は、Graph API のエラー コードを示し、message 要素には、エラー メッセージ文字列が含まれています。 この例では、応答本文は、読みやすくするためにインデントされています。

HTTP/1.1 202 Accepted
Cache-Control: no-cache
Pragma: no-cache
Content-Type: multipart/mixed; boundary=batchresponse_3ac28387-a100-4758-8998-8b9ec36f9fdc
Expires: -1
Server: Microsoft-IIS/8.5
ocp-aad-diagnostics-server-name: 1l3fvSoDCV+VKoBCuHRN+HIwCACBOck3dqmtCGj+aiU=
request-id: e434261b-c32f-48b4-b21d-3e1beab6d525
client-request-id: 236bf26e-b4e8-40a4-b6fb-d41105a7b178
x-ms-gateway-rewrite: false
x-ms-dirapi-data-contract-version: 1.5
ocp-aad-session-key: 9aOaAUxX95OZ0ctrYbeLUproN-37GypZXrss0PYKhEfqamKRG-C68hFcCw5h-ZCWFqBrXPrldGEnjq4CKKr0bW91tjrdo-BlwAqHxbP5jq4.FaXtVZni3cSsWFRMSjQAbjiluPcEvZofwp9OH3t1fyk
X-Content-Type-Options: nosniff
DataServiceVersion: 1.0;
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
X-Powered-By: ASP.NET
Date: Wed, 21 Jan 2015 21:13:25 GMT
Content-Length: 779

--batchresponse_3ac28387-a100-4758-8998-8b9ec36f9fdc
Content-Type: multipart/mixed; boundary=changesetresponse_72ba9a5a-2da3-4d39-ae4f-dd9527efd742--changesetresponse_72ba9a5a-2da3-4d39-ae4f-dd9527efd742
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 404 Not Found
X-Content-Type-Options: nosniff
DataServiceVersion: 3.0;
Content-Type: application/json;odata=minimalmetadata;streaming=true;charset=utf-8

{
  "odata.error":
    {
      "code":"Request_ResourceNotFound",
      "message":
        {
          "lang":"en",
          "value":"Resource 'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee' does not exist or one of its queried reference-property objects are not present."
        }
    }
}
--changesetresponse_72ba9a5a-2da3-4d39-ae4f-dd9527efd742----batchresponse_3ac28387-a100-4758-8998-8b9ec36f9fdc--

次の例では、参考用として上記の応答を生成したバッチを示します。 これには、3 人のユーザーをグループに追加する 1 つの変更セットが含まれています。 最後の 2 人のユーザーのオブジェクト ID は架空のものです: eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee および ffffffff-ffff-ffff-ffff-ffffffffffff。 バッチ URL と関連付けられた要求ヘッダーは簡潔性を保つため省略してあります。

--batch_36522ad7-fc75-4b56-8c71-56071383e77b 
Content-Type: multipart/mixed; boundary=changeset_5a769eb2-d1a7-4a10-94f6-d1a5ed5c4bc0 
Content-Length: 1432

--changeset_5a769eb2-d1a7-4a10-94f6-d1a5ed5c4bc0 
Content-Type: application/http 
Content-Transfer-Encoding: binary 

POST /contoso.onmicrosoft.com/groups/fc15e7ef-993f-4865-bf37-317d9b8017b8/$links/members?api-version=1.5 HTTP/1.1
Content-Type: application/json
Accept: application/json
Content-Length: 112
Host: graph.windows.net

{
  "url":"https://graph.windows.net/contoso.onmicrosoft.com/users/a71e4d1c-ce99-40dc-8d4b-390eac63e039"
}

--changeset_5a769eb2-d1a7-4a10-94f6-d1a5ed5c4bc0 
Content-Type: application/http 
Content-Transfer-Encoding: binary 

POST /contoso.onmicrosoft.com/groups/fc15e7ef-993f-4865-bf37-317d9b8017b8/$links/members?api-version=1.5 HTTP/1.1
Content-Type: application/json
Accept: application/json
Content-Length: 112
Host: graph.windows.net

{
  "url":"https://graph.windows.net/contoso.onmicrosoft.com/users/eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee
"
}

--changeset_5a769eb2-d1a7-4a10-94f6-d1a5ed5c4bc0 
Content-Type: application/http 
Content-Transfer-Encoding: binary 

POST /contoso.onmicrosoft.com/groups/fc15e7ef-993f-4865-bf37-317d9b8017b8/$links/members?api-version=1.5 HTTP/1.1
Content-Type: application/json
Accept: application/json
Content-Length: 112
Host: graph.windows.net

{
  "url":"https://graph.windows.net/contoso.onmicrosoft.com/users/ffffffff-ffff-ffff-ffff-ffffffffffff"
}

--changeset_5a769eb2-d1a7-4a10-94f6-d1a5ed5c4bc0----batch_36522ad7-fc75-4b56-8c71-56071383e77b--

その他のリソース