---
title: "xConnect検索結果のページング"
slug: "paginatingxconnect-search-results"
abstract: "GetBatchEnumerator()とGetBatchEnumeratorSync()メソッド、そしてSkip()とTake ()メソッドの使い方を使った結果のページ付け方法について。"
---
# xConnect検索結果のページング

結果をページ付けする方法は2通りあります:

-   推奨されている GetBatchEnumerator() / GetBatchEnumeratorSync() 方法を使う
-   Skip()法とTake()法の利用

ページ分けをしない場合は、パフォーマンスを保つために結果数をデフォルトのバッチサイズに制限します。データをエクスポートするには、データ抽出機能を使うべきです。

## ページと演奏

大量の結果をスキップすることは、非常に大きなバッチを要求するのと同じくらい非効率的です。999990件のレコードをスキップし、#99990を#10000000に表示するためには、検索提供者は最初の999990件を見つけてソートしなければなりません。たとえ10件ずつの99990件をスキップしても、各Skip() は新しいクエリとして扱われ、パフォーマンスへの影響がますます深刻になります。これはSolrやAzure Searchでも当てはまります。

.GetBatchEnumerator()および.GetBatchEnumeratorSync()メソッドは、連続バッチを順番に進めるために使われるカーソルを返します。各バッチにはカーソルマークが関連付けられています。カーソルマークはバイト配列で表され、大規模な結果セットを反復する際に位置情報ブックマークを付けます。これらの方法は、すでに見た結果をスキップすることでパフォーマンスを向上させます。つまり、レコード#99990をレコード#10000000に表示する際、最初の999990レコードは無視されます。

![cursor-mark-11.png](https://doc.sitecore.com/api/markdown-image/xp/ja/developers/91/sitecore-experience-platform/images/cursor-mark-11.png)

カーソルマークを使用する際には以下の点を念頭に置いてください:

-   カーソルマークではレコード#999990に直接スキップすることはできません。この点まですべての結果を繰り返し確認する必要があります。パフォーマンス向上は、新しいバッチが返されるたびに既に見た結果を探して並べ替える必要がないことにあります。
-   カーソルマークは寿命が短く、モデルの変更に耐性はありません。したがって、ページ付けのUIでカーソルマークに頼るべきではありません。例えば、30バッチを繰り返し処理する場合、30カーソルマークを永続化してページ番号として扱わないでください。

カーソルマークはエラーが発生した場合に検索操作を再開するために使用できます。例えば、1000バッチを反復処理中にバッチ999中にエラーが発生した場合、その時点でカーソルマークを保持することでバッチ999で再開できます。

ユーザーインターフェースで深いページングをサポートする場合は、無限スクロールの使用を検討してください。これにより結果セットを前後にページングする必要がなくなり、

詳細については、[Solrの結果のページ付け](https://cwiki.apache.org/confluence/display/solr/Pagination+of+Results) 、特に *「ディープページングのパフォーマンス問題*」のセクションを参照してください。

カーソルマークはシャード環境で特に重要になり、各シャードは100件の結果を返す必要があります。その後、100件ずつの3回の結果が集約され、上位100件がクライアントに返されます。

![cursor-mark-21.png](https://doc.sitecore.com/api/markdown-image/xp/ja/developers/91/sitecore-experience-platform/images/cursor-mark-21.png)

## 浅いページ展開 と 。スキップ() と 。テイク()

ごく一部の接触や相互作用を通じてインターテートしたい場合、.Skip() と .Take() の方法を使うことは許容されます。

using Sitecore.XConnect.Collection.Model;
using System.Linq;
using Sitecore.XConnect;
using Sitecore.XConnect.Client;

namespace Documentation
{
 public class SearchInteractionSkipTake
 {
 // Async example
 // Example query string: searchresults?page=4&pageSize=10
 public async void ExampleAsync(int pageSize, int page)
 {
 using (Sitecore.XConnect.Client.XConnectClient client = Sitecore.XConnect.Client.Configuration.SitecoreXConnectClientConfiguration.GetClient())
 {
 try
 {
 var skip = pageSize \* (page - 1);

 IAsyncQueryable<Sitecore.XConnect.Interaction> queryable = client.Interactions
 .Where(x => x.GetFacet<WebVisit>(CollectionModel.FacetKeys.WebVisit).Browser.BrowserMajorName == "Chrome")
 .Skip(skip)
 .Take(pageSize);

 var results = await queryable.ToSearchResults();

 var count = results.Count; // Actual count of all results

 var interactions = await results.Results.Select(x => x.Item).ToList();

 }
 catch (XdbExecutionException ex)
 {
 // Handle exception
 }
 }
 }

 public void ExampleSync(int pageSize, int page)
 {
 using (Sitecore.XConnect.Client.XConnectClient client = Sitecore.XConnect.Client.Configuration.SitecoreXConnectClientConfiguration.GetClient())
 {
 try
 {
 var skip = pageSize \* (page - 1);

 IAsyncQueryable<Sitecore.XConnect.Interaction> queryable = client.Interactions
 .Where(x => x.GetFacet<WebVisit>(CollectionModel.FacetKeys.WebVisit).Browser.BrowserMajorName == "Chrome")
 .Skip(skip)
 .Take(pageSize);

 // NOTE: No sync version of ToSearchResults exists
 // and it is the only way to get a count of actual results
 var results = Sitecore.XConnect.Client.XConnectSynchronousExtensions.SuspendContextLock(queryable.ToSearchResults);

 var items = results.Results.Select(x => x.Item); // Interactions
 var count = results.Count; // Total count
 }
 catch (XdbExecutionException ex)
 {
 // Handle exception
 }
 }
 }
 }
}

> !注常にSkip().Take()に電話し、決してTake().Skip()しないでください。

## 深いページ化 。GetBatchEnumerator()

以下の例は、大量の結果を反復処理する際の .GetBatchEnumerator() / .GetBatchEnumeratorSync() の使い方を示しています。

using Sitecore.XConnect.Collection.Model;
using System.Collections.Generic;
using System.Linq;
using Sitecore.XConnect;
using Sitecore.XConnect.Client;

namespace Documentation
{
 public class SearchInteractionCursorBasic
 {
 // Async example
 public async void ExampleAsync()
 {
 using (Sitecore.XConnect.Client.XConnectClient client = Sitecore.XConnect.Client.Configuration.SitecoreXConnectClientConfiguration.GetClient())
 {
 try
 {
 var results = client.Interactions
 .Where(x => x.GetFacet<WebVisit>(CollectionModel.FacetKeys.WebVisit).Browser.BrowserMajorName == "Chrome");

 var enumerator = await results.GetBatchEnumerator(200);

 var numberOfBatches = 0;

 // Enumerate through batches of 200
 while (await enumerator.MoveNext())
 {
 numberOfBatches++;

 // Loop through interactions in current batch
 foreach (var interaction in enumerator.Current)
 {
 // Do something for each interaction
 }
 }
 }
 catch (XdbExecutionException ex)
 {
 // Handle exception
 }
 }
 }

 // Sync example
 public void ExampleSync()
 {
 using (Sitecore.XConnect.Client.XConnectClient client = Sitecore.XConnect.Client.Configuration.SitecoreXConnectClientConfiguration.GetClient())
 {
 try
 {
 var results = client.Interactions
 .Where(x => x.GetFacet<WebVisit>(CollectionModel.FacetKeys.WebVisit).Browser.BrowserMajorName == "Chrome");

 var numberOfBatches = 0;

 var enumerator = results.GetBatchEnumeratorSync(200);

 // Enumerate through batches of 200
 while (enumerator.MoveNext())
 {
 numberOfBatches++;

 // Loop through interactions in current batch
 foreach (var interaction in enumerator.Current)
 {
 // Do something for each interaction
 }
 }
 }
 catch (XdbExecutionException ex)
 {
 // Handle exception
 }
 }
 }
 }
}

以下の例は、ブックマークを永続化し、例外が発生した場合に検索クエリを再開する方法を示しています。

using Sitecore.XConnect.Collection.Model;
using System.Collections.Generic;
using System.Linq;
using Sitecore.XConnect;
using Sitecore.XConnect.Client;

namespace Documentation
{
 public class SearchInteractionCursor
 {
 // Async example
 public async void ExampleAsync(byte bookmark)
 {
 using (Sitecore.XConnect.Client.XConnectClient client = Sitecore.XConnect.Client.Configuration.SitecoreXConnectClientConfiguration.GetClient())
 {
 byte bookmarkSave = null;

 try
 {
 var results = client.Interactions
 .Where(x => x.GetFacet<WebVisit>(CollectionModel.FacetKeys.WebVisit).Browser.BrowserMajorName == "Chrome");

 var enumerator = await results.GetBatchEnumerator(200);

 var numberOfBatches = 0;

 // Enumerate through batches of 200
 while (await enumerator.MoveNext())
 {
 bookmarkSave = enumerator.GetBookmark();
 numberOfBatches++;

 // Loop through interactions in current batch
 foreach (var interaction in enumerator.Current)
 {
 // Do something for each interaction
 }
 }
 }
 catch (XdbExecutionException ex)
 {
 // Retry using saved bookmark
 ExampleAsync(bookmarkSave);
 }
 }
 }

 // Sync example
 public void ExampleSync(byte bookmark)
 {
 using (Sitecore.XConnect.Client.XConnectClient client = Sitecore.XConnect.Client.Configuration.SitecoreXConnectClientConfiguration.GetClient())
 {
 byte bookmarkSave = null;

 try
 {
 var results = client.Interactions
 .Where(x => x.GetFacet<WebVisit>(CollectionModel.FacetKeys.WebVisit).Browser.BrowserMajorName == "Chrome");

 var numberOfBatches = 0;

 var enumerator = results.GetBatchEnumeratorSync(200);

 // Enumerate through batches of 200
 while (enumerator.MoveNext())
 {
 bookmarkSave = enumerator.GetBookmark();
 numberOfBatches++;

 // Loop through interactions in current batch
 foreach (var interaction in enumerator.Current)
 {
 // Do something for each interaction
 }
 }
 }
 catch (XdbExecutionException ex)
 {
 // Handle exception
 ExampleSync(bookmarkSave);
 }
 }
 }
 }
}