テーブルおよびインデックスのスキャン: .NET - Amazon DynamoDB

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

テーブルおよびインデックスのスキャン: .NET

Scan オペレーションは、Amazon DynamoDB のテーブルまたはインデックス内のすべての項目を読み込みます。

以下は、 AWS SDK for .NET 低レベル API を使用してテーブルをスキャンするステップです。

  1. AmazonDynamoDBClient クラスのインスタンスを作成します。

  2. ScanRequest クラスのインスタンスを作成して、スキャンオペレーションパラメータを指定します。

    必須パラメータは、テーブル名のみです。

  3. Scan メソッドを実行し、前述のステップで作成した ScanRequest オブジェクトを指定します。

以下の Reply テーブルは、フォーラムスレッドの返信を保存します。

>Reply ( <emphasis role="underline">Id</emphasis>, <emphasis role="underline">ReplyDateTime</emphasis>, Message, PostedBy )

テーブルには、さまざまなフォーラムスレッドに対するすべての返信が保持されます。したがってプライマリキーは、Id (パーティションキー) と ReplyDateTime (ソートキー) の両方で構成されます。次の C# のサンプルコードでは、テーブル全体をスキャンします。ScanRequest インスタンスは、スキャンするテーブルの名前を指定します。

AmazonDynamoDBClient client = new AmazonDynamoDBClient(); var request = new ScanRequest { TableName = "Reply", }; var response = client.Scan(request); var result = response.ScanResult; foreach (Dictionary<string, AttributeValue> item in response.ScanResult.Items) { // Process the result. PrintItem(item); }

オプションパラメータの指定

Scan メソッドでは、複数のオプションパラメータがサポートされています。たとえば、オプションでスキャンフィルターを使用して、スキャン結果をフィルタリングできます。スキャンフィルターでは、条件を評価する条件および属性の名前を指定できます。詳細については、「スキャン」を参照してください。

以下の C# コードは、ProductCatalog テーブルをスキャンして、料金が 0 未満の項目を検索します。このサンプルでは、次のオプションパラメータが指定されています。

  • 料金が 0 (エラー状態) 未満の項目のみを取得する FilterExpression パラメータ。

  • クエリ結果内の項目について取得する属性を指定する ProjectionExpression パラメータ。

以下の C# サンプルは、ProductCatalog テーブルをスキャンして、料金が 0 未満のすべての項目を検索できます。

var forumScanRequest = new ScanRequest { TableName = "ProductCatalog", // Optional parameters. ExpressionAttributeValues = new Dictionary<string,AttributeValue> { {":val", new AttributeValue { N = "0" }} }, FilterExpression = "Price < :val", ProjectionExpression = "Id" };

また、オプションの Limit パラメータを追加することで、ページサイズ、または 1 ページあたりの項目数を制限することもできます。Scan メソッドを実行するたびに、指定された数の項目を含む結果が 1 ページ取得されます。次のページを取得するには、前ページの最後の項目のプライマリキーの値を入力して、Scan メソッドを再度実行します。そうすることで、Scan メソッドが、次の項目のセットを返すことができます。この情報は、ExclusiveStartKey プロパティを設定することでリクエストに含めます。このプロパティは最初は null である場合があります。以降のページを取り出すには、このプロパティ値を更新して、前ページの最後の項目のプライマリキーにする必要があります。

次の C# コード例では、ProductCatalog テーブルをスキャンします。リクエストでは、オプションの Limit および ExclusiveStartKey パラメータを指定しています。do/while ループは、LastEvaluatedKey から null 値が返されるまで、一度に 1 ページのスキャンを継続します。

Dictionary<string, AttributeValue> lastKeyEvaluated = null; do { var request = new ScanRequest { TableName = "ProductCatalog", Limit = 10, ExclusiveStartKey = lastKeyEvaluated }; var response = client.Scan(request); foreach (Dictionary<string, AttributeValue> item in response.Items) { PrintItem(item); } lastKeyEvaluated = response.LastEvaluatedKey; } while (lastKeyEvaluated != null && lastKeyEvaluated.Count != 0);

例 - .NET を使用したスキャン

次の C# コードは、実行例を提供し、ProductCatalog テーブルをスキャンして、料金が 0 未満の項目を検索します。

次のサンプルをテストする step-by-step 手順については、「」を参照してください.NET コード例

using System; using System.Collections.Generic; using Amazon.DynamoDBv2; using Amazon.DynamoDBv2.Model; using Amazon.Runtime; namespace com.amazonaws.codesamples { class LowLevelScan { private static AmazonDynamoDBClient client = new AmazonDynamoDBClient(); static void Main(string[] args) { try { FindProductsForPriceLessThanZero(); Console.WriteLine("Example complete. To continue, press Enter"); Console.ReadLine(); } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine("To continue, press Enter"); Console.ReadLine(); } } private static void FindProductsForPriceLessThanZero() { Dictionary<string, AttributeValue> lastKeyEvaluated = null; do { var request = new ScanRequest { TableName = "ProductCatalog", Limit = 2, ExclusiveStartKey = lastKeyEvaluated, ExpressionAttributeValues = new Dictionary<string, AttributeValue> { {":val", new AttributeValue { N = "0" }} }, FilterExpression = "Price < :val", ProjectionExpression = "Id, Title, Price" }; var response = client.Scan(request); foreach (Dictionary<string, AttributeValue> item in response.Items) { Console.WriteLine("\nScanThreadTableUsePaging - printing....."); PrintItem(item); } lastKeyEvaluated = response.LastEvaluatedKey; } while (lastKeyEvaluated != null && lastKeyEvaluated.Count != 0); Console.WriteLine("To continue, press Enter"); Console.ReadLine(); } private static void PrintItem( Dictionary<string, AttributeValue> attributeList) { foreach (KeyValuePair<string, AttributeValue> kvp in attributeList) { string attributeName = kvp.Key; AttributeValue value = kvp.Value; Console.WriteLine( attributeName + " " + (value.S == null ? "" : "S=[" + value.S + "]") + (value.N == null ? "" : "N=[" + value.N + "]") + (value.SS == null ? "" : "SS=[" + string.Join(",", value.SS.ToArray()) + "]") + (value.NS == null ? "" : "NS=[" + string.Join(",", value.NS.ToArray()) + "]") ); } Console.WriteLine("************************************************"); } } }

例 - .NET を使用した並列スキャン

次の C# コードの例は並列スキャン方法を示します。プログラムは、ProductCatalog テーブルを削除してから再作成します。その後、テーブルにデータをロードします。データのロードが完了すると、プログラムは複数のスレッドを生成し、Scan リクエストを並列に発行します。最後に、プログラムはランタイム統計の要約を出力します。

次のサンプルをテストする step-by-step 手順については、「」を参照してください.NET コード例

using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Amazon.DynamoDBv2; using Amazon.DynamoDBv2.Model; using Amazon.Runtime; namespace com.amazonaws.codesamples { class LowLevelParallelScan { private static AmazonDynamoDBClient client = new AmazonDynamoDBClient(); private static string tableName = "ProductCatalog"; private static int exampleItemCount = 100; private static int scanItemLimit = 10; private static int totalSegments = 5; static void Main(string[] args) { try { DeleteExampleTable(); CreateExampleTable(); UploadExampleData(); ParallelScanExampleTable(); } catch (AmazonDynamoDBException e) { Console.WriteLine(e.Message); } catch (AmazonServiceException e) { Console.WriteLine(e.Message); } catch (Exception e) { Console.WriteLine(e.Message); } Console.WriteLine("To continue, press Enter"); Console.ReadLine(); } private static void ParallelScanExampleTable() { Console.WriteLine("\n*** Creating {0} Parallel Scan Tasks to scan {1}", totalSegments, tableName); Task[] tasks = new Task[totalSegments]; for (int segment = 0; segment < totalSegments; segment++) { int tmpSegment = segment; Task task = Task.Factory.StartNew(() => { ScanSegment(totalSegments, tmpSegment); }); tasks[segment] = task; } Console.WriteLine("All scan tasks are created, waiting for them to complete."); Task.WaitAll(tasks); Console.WriteLine("All scan tasks are completed."); } private static void ScanSegment(int totalSegments, int segment) { Console.WriteLine("*** Starting to Scan Segment {0} of {1} out of {2} total segments ***", segment, tableName, totalSegments); Dictionary<string, AttributeValue> lastEvaluatedKey = null; int totalScannedItemCount = 0; int totalScanRequestCount = 0; do { var request = new ScanRequest { TableName = tableName, Limit = scanItemLimit, ExclusiveStartKey = lastEvaluatedKey, Segment = segment, TotalSegments = totalSegments }; var response = client.Scan(request); lastEvaluatedKey = response.LastEvaluatedKey; totalScanRequestCount++; totalScannedItemCount += response.ScannedCount; foreach (var item in response.Items) { Console.WriteLine("Segment: {0}, Scanned Item with Title: {1}", segment, item["Title"].S); } } while (lastEvaluatedKey.Count != 0); Console.WriteLine("*** Completed Scan Segment {0} of {1}. TotalScanRequestCount: {2}, TotalScannedItemCount: {3} ***", segment, tableName, totalScanRequestCount, totalScannedItemCount); } private static void UploadExampleData() { Console.WriteLine("\n*** Uploading {0} Example Items to {1} Table***", exampleItemCount, tableName); Console.Write("Uploading Items: "); for (int itemIndex = 0; itemIndex < exampleItemCount; itemIndex++) { Console.Write("{0}, ", itemIndex); CreateItem(itemIndex.ToString()); } Console.WriteLine(); } private static void CreateItem(string itemIndex) { var request = new PutItemRequest { TableName = tableName, Item = new Dictionary<string, AttributeValue>() { { "Id", new AttributeValue { N = itemIndex }}, { "Title", new AttributeValue { S = "Book " + itemIndex + " Title" }}, { "ISBN", new AttributeValue { S = "11-11-11-11" }}, { "Authors", new AttributeValue { SS = new List<string>{"Author1", "Author2" } }}, { "Price", new AttributeValue { N = "20.00" }}, { "Dimensions", new AttributeValue { S = "8.5x11.0x.75" }}, { "InPublication", new AttributeValue { BOOL = false } } } }; client.PutItem(request); } private static void CreateExampleTable() { Console.WriteLine("\n*** Creating {0} Table ***", tableName); var request = new CreateTableRequest { AttributeDefinitions = new List<AttributeDefinition>() { new AttributeDefinition { AttributeName = "Id", AttributeType = "N" } }, KeySchema = new List<KeySchemaElement> { new KeySchemaElement { AttributeName = "Id", KeyType = "HASH" //Partition key } }, ProvisionedThroughput = new ProvisionedThroughput { ReadCapacityUnits = 5, WriteCapacityUnits = 6 }, TableName = tableName }; var response = client.CreateTable(request); var result = response; var tableDescription = result.TableDescription; Console.WriteLine("{1}: {0} \t ReadsPerSec: {2} \t WritesPerSec: {3}", tableDescription.TableStatus, tableDescription.TableName, tableDescription.ProvisionedThroughput.ReadCapacityUnits, tableDescription.ProvisionedThroughput.WriteCapacityUnits); string status = tableDescription.TableStatus; Console.WriteLine(tableName + " - " + status); WaitUntilTableReady(tableName); } private static void DeleteExampleTable() { try { Console.WriteLine("\n*** Deleting {0} Table ***", tableName); var request = new DeleteTableRequest { TableName = tableName }; var response = client.DeleteTable(request); var result = response; Console.WriteLine("{0} is being deleted...", tableName); WaitUntilTableDeleted(tableName); } catch (ResourceNotFoundException) { Console.WriteLine("{0} Table delete failed: Table does not exist", tableName); } } private static void WaitUntilTableReady(string tableName) { string status = null; // Let us wait until table is created. Call DescribeTable. do { System.Threading.Thread.Sleep(5000); // Wait 5 seconds. try { var res = client.DescribeTable(new DescribeTableRequest { TableName = tableName }); Console.WriteLine("Table name: {0}, status: {1}", res.Table.TableName, res.Table.TableStatus); status = res.Table.TableStatus; } catch (ResourceNotFoundException) { // DescribeTable is eventually consistent. So you might // get resource not found. So we handle the potential exception. } } while (status != "ACTIVE"); } private static void WaitUntilTableDeleted(string tableName) { string status = null; // Let us wait until table is deleted. Call DescribeTable. do { System.Threading.Thread.Sleep(5000); // Wait 5 seconds. try { var res = client.DescribeTable(new DescribeTableRequest { TableName = tableName }); Console.WriteLine("Table name: {0}, status: {1}", res.Table.TableName, res.Table.TableStatus); status = res.Table.TableStatus; } catch (ResourceNotFoundException) { Console.WriteLine("Table name: {0} is not found. It is deleted", tableName); return; } } while (status == "DELETING"); } } }