Microsoft Graph SDK を使用してコレクションをページ表示する
[アーティクル]
07/06/2023
8 人の共同作成者
フィードバック
この記事の内容
パフォーマンス上の理由から、エンティティのコレクションはページに分割されることが多く、各ページには次のページへの URL が返されます。 PageIterator クラスを使用すると、ページコレクションの使用が簡略化されます。 PageIterator は、現在のページの列挙と後続のページの要求を自動的に処理します。
最初の要求で追加の要求ヘッダーを送信する場合、これらのヘッダーは、後続のページ要求に既定では含まれません。 これらのヘッダーを後続のリクエストで送信する必要がある場合は、明示的に設定する必要があります。
すべてのメッセージを反復処理する
次の例は、ユーザーのメールボックス内のすべてのメッセージを反復処理する方法を示しています。
ヒント
次の使用例は、デモ目的で パラメーターを top
使用して小さなページ サイズを設定します。 ページ サイズを最大 999 に設定して、必要な要求の数を最小限に抑えることができます。
var messages = await graphClient.Me.Messages
.GetAsync(requestConfiguration =>
{
requestConfiguration.QueryParameters.Top = 10;
requestConfiguration.QueryParameters.Select =
new string[] { "sender", "subject", "body" };
requestConfiguration.Headers.Add(
"Prefer", "outlook.body-content-type=\"text\"");
});
if (messages == null)
{
return;
}
var pageIterator = PageIterator<Message, MessageCollectionResponse>
.CreatePageIterator(
graphClient,
messages,
// Callback executed for each item in
// the collection
(msg) =>
{
Console.WriteLine(msg.Subject);
return true;
},
// Used to configure subsequent page
// requests
(req) =>
{
// Re-add the header to subsequent requests
req.Headers.Add("Prefer", "outlook.body-content-type=\"text\"");
return req;
});
await pageIterator.IterateAsync();
import (
"context"
"fmt"
"log"
"time"
abstractions "github.com/microsoft/kiota-abstractions-go"
graph "github.com/microsoftgraph/msgraph-sdk-go"
graphcore "github.com/microsoftgraph/msgraph-sdk-go-core"
"github.com/microsoftgraph/msgraph-sdk-go/models"
"github.com/microsoftgraph/msgraph-sdk-go/users"
)
headers := abstractions.NewRequestHeaders()
headers.Add("Prefer", "outlook.body-content-type=\"text\"")
var pageSize int32 = 10
query := users.ItemMessagesRequestBuilderGetQueryParameters{
Select: []string{"body", "sender", "subject"},
Top: &pageSize,
}
options := users.ItemMessagesRequestBuilderGetRequestConfiguration{
Headers: headers,
QueryParameters: &query,
}
result, err := graphClient.Me().Messages().Get(context.Background(), &options)
if err != nil {
log.Fatalf("Error getting messages: %v\n", err)
}
// Initialize iterator
pageIterator, err := graphcore.NewPageIterator[*models.Message](
result,
graphClient.GetAdapter(),
models.CreateMessageCollectionResponseFromDiscriminatorValue)
if err != nil {
log.Fatalf("Error creating page iterator: %v\n", err)
}
// Any custom headers sent in original request should also be added
// to the iterator
pageIterator.SetHeaders(headers)
// Iterate over all pages
err = pageIterator.Iterate(
context.Background(),
func(message *models.Message) bool {
fmt.Printf("%s\n", *message.GetSubject())
// Return true to continue the iteration
return true
})
if err != nil {
log.Fatalf("Error iterating over messages: %v\n", err)
}
注:
現在、Microsoft Graph Java SDK には PageIterator クラスがありません。 代わりに、次のコードに示すように各ページを要求する必要があります。
MessageCollectionPage messagesPage = graphClient.me().messages()
.buildRequest(
new HeaderOption("Prefer", "outlook.body-content-type=\"text\""))
.select("sender,subject,body").top(10).get();
while (messagesPage != null) {
final List<Message> messages = messagesPage.getCurrentPage();
for (Message message : messages) {
System.out.println(message.subject);
}
// Get the next page
final MessageCollectionRequestBuilder nextPage = messagesPage.getNextPage();
if (nextPage == null) {
break;
} else {
messagesPage = nextPage.buildRequest(
// Re-add the header to subsequent requests
new HeaderOption("Prefer", "outlook.body-content-type=\"text\""))
.get();
}
}
const response: PageCollection = await graphClient
.api('/me/messages?$top=10&$select=sender,subject,body')
.header('Prefer', 'outlook.body-content-type="text"')
.get();
// A callback function to be called for every item in the collection.
// This call back should return boolean indicating whether not to
// continue the iteration process.
const callback: PageIteratorCallback = (message: Message) => {
console.log(message.subject);
return true;
};
// A set of request options to be applied to
// all subsequent page requests
const requestOptions: GraphRequestOptions = {
// Re-add the header to subsequent requests
headers: {
Prefer: 'outlook.body-content-type="text"',
},
};
// Creating a new page iterator instance with client a graph client
// instance, page collection response from request and callback
const pageIterator = new PageIterator(
graphClient,
response,
callback,
requestOptions
);
// This iterates the collection until the nextLink is drained out.
await pageIterator.iterate();
イテレーションの停止と再開
一部のシナリオでは、他のアクションを実行するためにイテレーション プロセスを停止する必要があります。 イテレーション コールバックからを返すことで、イテレーションを false
一時停止できます。 PageIterator で メソッドをresume
呼び出すことで、イテレーションを再開できます。
int count = 0;
int pauseAfter = 25;
var messages = await graphClient.Me.Messages
.GetAsync(requestConfiguration =>
{
requestConfiguration.QueryParameters.Top = 10;
requestConfiguration.QueryParameters.Select =
new string[] { "sender", "subject" };
});
if (messages == null)
{
return;
}
var pageIterator = PageIterator<Message, MessageCollectionResponse>
.CreatePageIterator(
graphClient,
messages,
(msg) =>
{
Console.WriteLine(msg.Subject);
count++;
// If we've iterated over the limit,
// stop the iteration by returning false
return count < pauseAfter;
});
await pageIterator.IterateAsync();
while (pageIterator.State != PagingState.Complete)
{
Console.WriteLine("Iteration paused for 5 seconds...");
await Task.Delay(5000);
// Reset count
count = 0;
await pageIterator.ResumeAsync();
}
import (
"context"
"fmt"
"log"
"time"
abstractions "github.com/microsoft/kiota-abstractions-go"
graph "github.com/microsoftgraph/msgraph-sdk-go"
graphcore "github.com/microsoftgraph/msgraph-sdk-go-core"
"github.com/microsoftgraph/msgraph-sdk-go/models"
"github.com/microsoftgraph/msgraph-sdk-go/users"
)
var pageSize int32 = 10
query := users.ItemMessagesRequestBuilderGetQueryParameters{
Select: []string{"body", "sender", "subject"},
Top: &pageSize,
}
options := users.ItemMessagesRequestBuilderGetRequestConfiguration{
QueryParameters: &query,
}
result, err := graphClient.Me().Messages().Get(context.Background(), &options)
if err != nil {
log.Fatalf("Error getting messages: %v\n", err)
}
// Initialize iterator
pageIterator, err := graphcore.NewPageIterator[*models.Message](
result,
graphClient.GetAdapter(),
models.CreateMessageCollectionResponseFromDiscriminatorValue)
if err != nil {
log.Fatalf("Error creating page iterator: %v\n", err)
}
// Pause iterating after 25
var count, pauseAfter = 0, 25
// Iterate over all pages
err = pageIterator.Iterate(
context.Background(),
func(message *models.Message) bool {
count++
fmt.Printf("%d: %s\n", count, *message.GetSubject())
// Once count = 25, this returns false,
// Which pauses the iteration
return count < pauseAfter
})
if err != nil {
log.Fatalf("Error iterating over messages: %v\n", err)
}
// Pause 5 seconds
fmt.Printf("Iterated first %d messages, pausing for 5 seconds...\n", pauseAfter)
time.Sleep(5 * time.Second)
fmt.Printf("Resuming iteration...\n")
// Resume iteration
err = pageIterator.Iterate(
context.Background(),
func(message *models.Message) bool {
count++
fmt.Printf("%d: %s\n", count, *message.GetSubject())
// Return true to continue the iteration
return true
})
if err != nil {
log.Fatalf("Error iterating over messages: %v\n", err)
}
// not supported in java SDK
let count = 0;
const pauseAfter = 25;
const response: PageCollection = await graphClient
.api('/me/messages?$top=10&$select=sender,subject,body')
.get();
const callback: PageIteratorCallback = (message: Message) => {
console.log(message.subject);
count++;
// If we've iterated over the limit,
// stop the iteration by returning false
return count < pauseAfter;
};
const pageIterator = new PageIterator(graphClient, response, callback);
await pageIterator.iterate();
while (!pageIterator.isComplete()) {
console.log('Iteration paused for 5 seconds...');
await new Promise((resolve) => setTimeout(resolve, 5000));
// Reset count
count = 0;
await pageIterator.resume();
}