大規模のファイル検出および変更検出のベスト プラクティス

SharePoint と OneDrive には、何百万ものファイルが保存されます。 すべてのファイルと大規模な変更を理解しようとするときは、適切な呼び出しパターンを使用することが重要です。 従来、アトミック レベルでファイルにアクセスするための API は多数あります。 これらの API の多くは、大規模な操作には効率的ではありませんが、単一のユーザー操作に適しています。 このガイダンスでは、アプリケーションが最大のパフォーマンスと効率で Office 365 と統合されるように、Office 365 テナントまたは OneDrive を監視する方法について説明します。 通常、このような種類のニーズがあるアプリケーションには、同期エンジン、バックアップ プロバイダー、検索インデクサー、分類エンジン、およびデータ損失防止プロバイダーがあります。

適切なアクセス許可の取得

ユーザーとの信頼関係を構築するには、アプリが機能するために必要なアクセス許可範囲の正しい最小セットを使用することが重要です。 ほとんどのスキャン アプリケーションは、アプリケーションのアクセス許可を使用して動作しようとします。これは、アプリケーションが特定のユーザーから独立して実行されていることを示します。 ファイルにアクセスするには、Files.Read.All または Files.ReadWrite.All スコープを要求する必要があります。 すべてのサイト コレクションの一覧を含む SharePoint リソースにアクセスするには、Sites.Read.All または Sites.ReadWrite.All が適切です。 アクセス許可を正しく処理するには、Sites.FullControl.All を要求する必要もあります。

承認の種類、アクセス許可の範囲、およびユーザー

Microsoft Azureでアプリケーションのアクセス許可を構成する場合は、アプリケーションのアクセス許可と委任されたアクセス許可を選択できます。 前述のように、ほとんどのスキャン アプリケーションではアプリケーションの アクセス許可が必要になります。 委任されたアクセス許可では、グローバルではなく、サインインしているユーザーのコンテキストでアプリケーションを操作する必要があります。 委任されたモデルでは、現在のユーザーがアクセスできるコンテンツに制限されます。

注意すべきアクセス許可の重要な側面の 1 つは、管理者がアプリケーションのアクセス許可 (委任されたアクセス許可ではなく) を要求するアプリケーションにアクセス許可を付与する場合、アクセス許可付与は管理者ユーザーではなくテナントとアプリケーションに関連付けられているということです。 管理者はアクセス権を付与する必要がありますが、アクセス許可は、アプリケーションによって要求されたリソース スコープへのアクセスを超えて、アプリケーションに対する特別な管理アクセス許可を付与しません。

SharePoint と OneDrive から大量のデータを処理するアプリケーションの場合は、次のような一貫した呼び出しパターンに従う必要があります。

  1. Discover – スキャンする場所を構成します。
  2. Crawl – 関心のあるファイルのセット全体を検出して処理します。
  3. Notify – 通知を使用して、これらのファイルへの変更を監視します。
  4. Process changes – デルタ クエリを使用して変更されたファイルのみを再処理します。

パターンは次の図のようになります。 この記事では、実装の各手順について詳しく説明します。

Microsoft Graphとクライアント アプリケーション間の呼び出しフローのスキャン

これらの各要素には、Microsoft Graph API と既存の SharePoint API でそれらを実現するためのメカニズムがいくつかあります。 この記事の目的は、各タスクを完了するための現時点で利用できる最適な方法を提供することです。

スキャンする場所を検出する

アプリケーションでスキャンする場所を構成するのは、現在の手動プロセスです。 多くの場合、この手順ではユーザー向けのアプリケーション エクスペリエンスを提供する必要があります。この機能を公開する方法と、それがすべてのユーザーに公開されるか、管理者だけに公開されるかは、ユーザー次第です。 どのユーザーの OneDrive と、スキャンする SharePoint サイト コレクションとサブサイトをスキャンするかを決定する必要があります。

各ユーザーの OneDrive には、監視できる ドライブが 1 つ含まれています。 SharePoint サイト コレクションとサブサイトには、サイト内のドキュメント ライブラリごとに 1 つずつ、複数のドライブを含めることができます。 /drives エンドポイントを使用して、サイト内の各ドライブを検出できます。 たとえば、テナントのルート サイト内のすべてのドライブを取得するには、次を使用できます:

https://graph.microsoft.com/v1.0/sites/root/drives

ドライブは、大規模なファイル アクティビティの開始点です。 これらのドライブを使用して、ファイルの完全な一覧を取得し、通知用の Webhook を接続し、デルタ クエリを使用してドライブ内の項目に対する変更のセットを取得します。

SharePoint サイト コレクションと OneDrive for Business ドライブを検索する方法

アプリケーションのアクセス許可で Microsoft Graph を使用すると、OneDrive for Business ドライブを含むサイトをはじめとするサイト コレクションの完全な一覧を取得できます。 この一覧を取得するには、次の API 呼び出しを使用します:

GET /sites

サイト列挙 API は、デルタ クエリをサポートして、サイト構造に対する新しいサイトの作成または変更に関する情報を取得します。 サイト列挙のデルタ クエリのサポートは、現在、Microsoft Graph ベータ版にロールアウトされています。 デルタ クエリの詳細については、この後もお読みください。

新しいサイト コレクションに関する通知を受信するには、Microsoft Graph のサブスクリプション エンドポイントを使用して Web フックにサブスクライブすることができます。 これらの通知のターゲット リソースは /sites です。 新しいサイト コレクションが作成または削除されたとき、およびサブサイトまたはリストが作成されたときに通知を受け取ります。

デルタ クエリを使用したクロールと処理

ドライブ内のファイルの最初の一覧を取得するには、パラメーターを指定しない 1 つのデルタ クエリを呼び出します。 デルタ クエリは、すべてのコンテンツの初期クロールと、その後の特定の時点からの変更をアプリに提供します。 デルタ クエリは、呼び出されるたびに将来の変更を取得するために必要なリンクを返します。

たとえば、SharePoint サイトの既定のドキュメント ライブラリ内のすべてのファイルを取得する場合は、次のクエリを使用できます:

/sites/{siteId}/drive/root/delta

この API は、ドライブ内のすべてのファイルを表す結果のページを返します。 返された を使用してファイルのすべてのページを取得した後、返された @odata.nextLinkを使用してデルタ クエリを再度作成し、最後にデルタ クエリを呼び出してから @odata.deltaLink 変更を取得できます。 後で @odata.deltaLink 変更を効率的に確認できるように、返される URL は常に保持してください。

デルタ クエリによって返されるリンクは次のようになります:

{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#Collection(driveItem)",
    "@odata.deltaLink": "https://graph.microsoft.com/v1.0/me/drive/root/delta?$select=*%2csharepointIds&token=MzslMjM0OyUyMzE7MzsyM2YwNDVhMS1lNmRmLTQ1N2MtOGQ5NS1hNmViZDVmZWRhNWQ7NjM2NzExNzY2MzIxMDcwMDAwOzE5ODAzMzU5ODslMjM7JTIzOyUyMzQ",
    "value": [
        {
            "@odata.type": "#microsoft.graph.driveItem",
            "createdDateTime": "2017-07-27T02:41:36Z",
…
}

詳細なサンプルについては、デルタ クエリのドキュメントを参照してください。

デルタ クエリは、driveItems の配列を返します。 特定の情報が必要なことが事前にわかっている場合は、デルタ クエリを使用して select ステートメントにその情報を含めることができます。 さらに必要に応じて、特定の driveItem の要求でデルタ呼び出しをフォローアップすることもできます。 デルタ クエリは、変更に対してクエリを実行する必要がある項目の数を絞り込むのに役立ち、アプリケーションがより効率のいいものになります。

Webhook を使用して変更の通知を受け取る

ドライブで発生する変更にデルタ クエリを最大限に活用するには、戻って来て変更を要求するタイミングを知るための効果的な戦略が必要です。 以前は、一定の間隔で OneDrive と SharePoint をポーリングするアプリを作成し、自分で変更を列挙していたかもしれません。 デルタ クエリでは、列挙部分が自動的に実行されるため、戻るタイミングを知るだけでよくなります。 Webhook を使用すると、サービスのポーリングを回避し、関心のある変更が発生したときに通知を受け取ることができます。 サービスを繰り返しポーリングしたり高いレートでポーリングしたりすると、過剰な呼び出しパターンが原因でアプリが調整を受けることができます。

Webhook は、API for Microsoft Graph のサブスクリプションを使用してアタッチされます。 Microsoft Graph Webhook と Subscriptions API に関する完全なドキュメントは、Microsoft Graph のサイトにあります。

特定のリソース (この場合はドライブ) に関連付けられているサブスクリプションを作成する必要があります。 ドライブは Webhook の “更新” 変更の種類をサポートしています。 "更新" とは、ドライブ内のコンテンツが変更されたか、新しいコンテンツが追加または削除されたことを示します。 Webhook サブスクリプションには、定期的にさいしんの情報に更新する必要があるタイムアウトが関連付けられています。 サブスクリプションを最新の方法に更新する方法については、前述のドキュメントを参照してください。 最初のクロールと Webhook の設定の間に発生した変更を見逃さないように、Webhook にサブスクライブした直後に、最後の変更トークンを使ってデルタ クエリを使用することをお勧めします。

Webhook がアプリケーション通知を送信する場合でも、定期的な差分クエリを提供して、通知の受信から長い時間が経過しているように見える場合に変更を見逃さないようにすることができます。 この定期的なチェックは、1 日に 1 回以下の頻度にすることをお勧めします。 デルタ クエリを使用すると、システム内の変更を簡単にキャッチアップし、見逃すことはありません。

セキュリティ イベントの Webhook 通知の受信

OneDrive と SharePoint では、セキュリティ イベントのアプリケーション通知の送信がサポートされています。 これらのイベントにサブスクライブするには、"prefer:includesecuritywebhooks" ヘッダーを要求に追加して Webhook を登録する必要があります。 Webhook が登録されると、項目に対するアクセス許可が変更されたときに通知を受け取ります。 このヘッダーは、SharePoint と OneDrive for Business には適用できますが、コンシューマー向け OneDrive アカウントには適用できません。

変更の処理

アプリケーションが Webhook を介して通知を受信したら、すぐに 202 - Accepted コードを Microsoft Graph に送り返して通知の確認をする必要があります。 時間のかかる処理を開始する前に、このコードを送信する必要があります。 これを行わないと、さらに再試行が送信され、これをアプリが誤った通知とみなす可能性があります。

最新の変更に対する差分クエリを使用して受信確認をフォローアップすると、アプリは最新の状態になるはずです。 特定のドライブで大量のトラフィック パターンが予想される場合は、各変更通知の後ではなく、より短い間隔でデルタ クエリを呼び出すことを考慮してください。 また、deltaLink パラメーターに返された新しい値を格納して、API を再度呼び出す新しいトークンを取得してください。

処理で個々のファイルの内容をダウンロードする必要がある場合は、cTag プロパティを使用して、前回のダウンロード以降にファイルの内容が変更されたかどうかを判断できます。 ファイルをダウンロードすることがわかれば、デルタ クエリ応答で返される DriveItem の /content プロパティにアクセスできます。

アクセス許可の階層のスキャン

既定では、デルタ クエリの応答には、親からアクセス許可を継承していて、それ自体直接の共有変更を行っていなくても、アイテムの共有情報が含まれます。 デルタ クエリ応答には、コンテンツまたはメタデータに直接変更を加えた項目と、変更された項目の親階層のみが含まれることに注意してください。 通常は、これにより、共有情報が変更されたアイテムだけでなく、すべてのアイテムのアクセス許可の詳細を取得するためフォローアップコールが発生します。 デルタ クエリ要求に "Prefer: hierarchysharing" ヘッダーを追加することで、アクセス許可の変更がどのように行われるかについての理解を深めることができます。

"Prefer: hierarchicalsharing" ヘッダーを指定すると、アクセス許可の階層のルートに共有情報、および明示的に共有の変更があるアイテムが返されます。 共有の変更によりアイテムから共有が削除される場合は、空の共有ファセットを見つけて、親から継承するアイテムと、一意ではあるが共有リンクがないアイテムを区別します。 また、この空の共有ファセットが、初期スコープを決定するために共有されていないアクセス許可階層のルートにも表示されます。

多くのスキャンの中で、アクセス許可の変更に特に関心がある可能性があります。 デルタ クエリ応答で、アクセス許可が変更された結果として、どの変更が行われたのかを明確にするために、"Prefer: deltashowsharingchanges" ヘッダーを指定することができます。 このヘッダーが指定されると、アクセス許可の変更によりデルタ クエリ応答に表示されるすべてのアイテムが、Microsoft Graphに対して呼び出すときに "@microsoft.graph.sharedChanged":"True" OData 注釈が存在します。SharePoint または OneDrive API を直接使用する場合、注釈は "@oneDrive.sharedChanged":"True" になります。 セキュリティ Webhook と同様、この機能は SharePoint と OneDrive for Business には適用できますが、コンシューマーの OneDrive アカウントには適用されません。

調整が行われるとどうなりますか?

一部のシナリオでは、アプリケーションがMicrosoft Graphから 429 または 503 応答を受け取る場合があります。 これは、要求が現在調整されていることを示します。 注意すべき点の 1 つは、SharePoint が各顧客テナントでのアプリケーションの使用に基づいてアプリケーションを調整することです。 テナント内の 1 つのリソースに対する要求を処理すると、その同じテナントに対して別のリソースを呼び出すリソースが少なくなります。 最終的には、アプリがスロットル応答を受け取る理由は複数あり、そうした状況でアプリが正しく応答することが重要です。

429 または 503 応答コードの受信から回復するには、応答ヘッダーの Retry-After フィールドで指定された期間待機した後、もう一度お試しください。 調整が引き続き行われると、Retry-After 値が時間の経過と共に長くなる可能性があるため、システムを回復することができます。 呼び出し応答前の期間が経過しても再試行を受け付けなかったアプリは、不正な呼び出しパターンが原因でブロックされます。

429 または 503 の回復を待機している場合は、サービスに対して行っているその他のすべての要求を一時停止する必要があります。 これは、マルチスレッド シナリオで特に重要です。 調整の応答を受信している間に追加の呼び出しを作成すると、アプリが調整を受けなくなるまでの時間が長くなります。

Microsoft Graph リソースと調整のしくみの詳細については、Microsoft Graph 調整ガイドを参照してください。