테이블 및 인덱스 쿼리: .NET - Amazon DynamoDB

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

테이블 및 인덱스 쿼리: .NET

Query작업으로 Amazon DynamoDB 에서 테이블이나 보조 인덱스를 쿼리할 수 있습니다. 파티션 키 값과 등식 조건을 입력해야 합니다. 테이블 또는 인덱스에 정렬 키가 있는 경우 정렬 키 값과 조건을 제공하여 결과를 구체화할 수 있습니다.

다음은 하위 수준 AWS SDK for .NET API를 사용하여 테이블을 쿼리하는 단계입니다.

  1. AmazonDynamoDBClient 클래스의 인스턴스를 만듭니다.

  2. QueryRequest 클래스의 인스턴스를 만들고 쿼리 작업 파라미터를 제공합니다.

  3. 실행 중인Query메서드를 제공 하 고QueryRequest개체를 이전 단계에서 생성한 것입니다.

    응답에는 쿼리에서 반환한 모든 항목을 제공하는 QueryResult 객체가 포함되어 있습니다.

다음은 위에서 설명한 작업을 실행하는 C# 코드 예제입니다. 예를 들어, 포럼 스레드에 대한 댓글을 저장하는 Reply 테이블이 있다고 가정합니다. 자세한 내용은 DynamoDB 에서 테이블 생성 및 코드 예제에 대한 데이터 로드 단원을 참조하세요.

Reply Id, ReplyDateTime, ... )

각 포럼 스레드에는 고유 ID가 있으며 회신 수는 0개 이상일 수 있습니다. 따라서 기본 키도 Id(파티션 키)와 ReplyDateTime(정렬 키), 두 가지로 구성됩니다.

다음 쿼리에서는 특정 스레드 주제에 대한 모든 회신을 검색합니다. 이 쿼리를 실행하려면 테이블 이름과 Subject 값을 모두 입력해야 합니다.

AmazonDynamoDBClient client = new AmazonDynamoDBClient(); var request = new QueryRequest { TableName = "Reply", KeyConditionExpression = "Id = :v_Id", ExpressionAttributeValues = new Dictionary<string, AttributeValue> { {":v_Id", new AttributeValue { S = "Amazon DynamoDB#DynamoDB Thread 1" }}} }; var response = client.Query(request); foreach (Dictionary<string, AttributeValue> item in response.Items) { // Process the result. PrintItem(item); }

옵션 파라미터 지정

Query 메서드는 여러 가지 선택적 파라미터를 지원합니다. 예를 들어 조건을 지정하여 이전 쿼리의 쿼리 결과를 필요에 따라 좁혀 과거 2주간의 회신을 반환할 수 있습니다. 이 조건을조건 정렬 키를 사용할 수 있습니다. DynamoDB 는 기본 키의 정렬 키에 대해 지정하는 쿼리 조건을 평가하기 때문입니다. 다른 선택적 파라미터를 지정하여 쿼리 결과의 항목에서 특정 속성 목록만 가져올 수 있습니다. 자세한 내용은 단원을 참조하십시오.Query.

다음 C# 코드 예제는 지난 15일간 게시된 포럼 스레드 댓글을 검색합니다. 이 예제에서 지정하는 옵션 파라미터는 다음과 같습니다.

  • KeyConditionExpression은 과거 15일간의 응답만 가져옵니다.

  • ProjectionExpression 파라미터는 속성 목록을 지정하여 쿼리 결과의 항목을 가져옵니다.

  • ConsistentRead 파라미터는 강력한 일관된 읽기(Strongly Consistent Read)를 수행합니다.

DateTime twoWeeksAgoDate = DateTime.UtcNow - TimeSpan.FromDays(15); string twoWeeksAgoString = twoWeeksAgoDate.ToString(AWSSDKUtils.ISO8601DateFormat); var request = new QueryRequest { TableName = "Reply", KeyConditionExpression = "Id = :v_Id and ReplyDateTime > :v_twoWeeksAgo", ExpressionAttributeValues = new Dictionary<string, AttributeValue> { {":v_Id", new AttributeValue { S = "Amazon DynamoDB#DynamoDB Thread 2" }}, {":v_twoWeeksAgo", new AttributeValue { S = twoWeeksAgoString }} }, ProjectionExpression = "Subject, ReplyDateTime, PostedBy", ConsistentRead = true }; var response = client.Query(request); foreach (Dictionary<string, AttributeValue> item in response.Items) { // Process the result. PrintItem(item); }

또한 필요할 경우 옵션으로 Limit 파라미터를 추가하여 페이지 크기 또는 페이지당 항목 수를 제한할 수 있습니다. 실행할 때마다Query메서드를 호출할 경우 지정된 항목 수가 있는 결과 한 페이지를 가져옵니다. 다음 페이지를 가져오려면Query메서드가 다음 항목 세트를 반환할 수 있도록 메서드를 다시 호출할 수 있도록 메서드를 다시 실행합니다. ExclusiveStartKey 속성을 설정하여 요청 시 이 정보를 제공합니다. 이 속성의 초기 값은 null이 될 수 있습니다. 연이어 다음 페이지까지 가져오려면 이 속성 값을 이전 페이지에서 마지막 항목의 기본 키로 업데이트해야 합니다.

다음 C# 예제는 Reply 테이블을 쿼리합니다. 요청에서 옵션으로 LimitExclusiveStartKey 파라미터를 지정합니다. do/while 루프는 LastEvaluatedKey가 null 값을 반환할 때까지 계속해서 한 페이지를 스캔합니다.

Dictionary<string,AttributeValue> lastKeyEvaluated = null; do { var request = new QueryRequest { TableName = "Reply", KeyConditionExpression = "Id = :v_Id", ExpressionAttributeValues = new Dictionary<string, AttributeValue> { {":v_Id", new AttributeValue { S = "Amazon DynamoDB#DynamoDB Thread 2" }} }, // Optional parameters. Limit = 1, ExclusiveStartKey = lastKeyEvaluated }; var response = client.Query(request); // Process the query result. foreach (Dictionary<string, AttributeValue> item in response.Items) { PrintItem(item); } lastKeyEvaluated = response.LastEvaluatedKey; } while (lastKeyEvaluated != null && lastKeyEvaluated.Count != 0);

예 - 쿼리AWS SDK for .NET

다음 테이블에는 포럼 모음에 대한 정보가 저장됩니다. 자세한 내용은 DynamoDB 에서 테이블 생성 및 코드 예제에 대한 데이터 로드 단원을 참조하세요.

Forum ( Name, ... ) Thread ( ForumName, Subject, Message, LastPostedBy, LastPostDateTime, ...) Reply ( Id, ReplyDateTime, Message, PostedBy, ...)

이 예에서는 포럼 “DynamoDB” 포럼에서 “DynamoDB Thread 1"스레드에 대한 댓글 검색”의 변형 작업을 실행합니다.

  • 스레드에 대한 회신을 찾습니다.

  • 스레드에 대한 회신을 찾습니다. Limit 쿼리 파라미터를 지정하여 페이지 크기를 설정합니다.

    이 기능은 다중 페이지 결과를 처리하기 위해 페이지 매김을 사용하는 경우를 보여줍니다. DynamoDB 에는 페이지 크기 제한이 있기 때문에 결과가 페이지 크기를 초과할 경우 결과의 첫 페이지만 볼 수 있습니다. 이 코딩 패턴에서는 코드가 쿼리 결과의 모든 페이지를 처리합니다.

  • 지난 15일 간에 해당하는 회신을 찾습니다.

  • 특정 날짜 범위에 해당하는 회신을 찾습니다.

    앞서 다룬 두 쿼리 모두 정렬 키 조건을 지정하여 쿼리 결과를 좁히고 여러 선택적 쿼리 파라미터를 사용하는 방법을 보여 줍니다.

다음 예제를 테스트하기 위한 단계별 지침은 .NET 코드 예제 단원을 참조하십시오.

/** * Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * This file is licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. A copy of * the License is located at * * http://aws.amazon.com/apache2.0/ * * This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ using System; using System.Collections.Generic; using Amazon.DynamoDBv2; using Amazon.DynamoDBv2.Model; using Amazon.Runtime; using Amazon.Util; namespace com.amazonaws.codesamples { class LowLevelQuery { private static AmazonDynamoDBClient client = new AmazonDynamoDBClient(); static void Main(string[] args) { try { // Query a specific forum and thread. string forumName = "Amazon DynamoDB"; string threadSubject = "DynamoDB Thread 1"; FindRepliesForAThread(forumName, threadSubject); FindRepliesForAThreadSpecifyOptionalLimit(forumName, threadSubject); FindRepliesInLast15DaysWithConfig(forumName, threadSubject); FindRepliesPostedWithinTimePeriod(forumName, threadSubject); Console.WriteLine("Example complete. To continue, press Enter"); Console.ReadLine(); } catch (AmazonDynamoDBException e) { Console.WriteLine(e.Message); Console.ReadLine(); } catch (AmazonServiceException e) { Console.WriteLine(e.Message); Console.ReadLine(); } catch (Exception e) { Console.WriteLine(e.Message); Console.ReadLine(); } } private static void FindRepliesPostedWithinTimePeriod(string forumName, string threadSubject) { Console.WriteLine("*** Executing FindRepliesPostedWithinTimePeriod() ***"); string replyId = forumName + "#" + threadSubject; // You must provide date value based on your test data. DateTime startDate = DateTime.UtcNow - TimeSpan.FromDays(21); string start = startDate.ToString(AWSSDKUtils.ISO8601DateFormat); // You provide date value based on your test data. DateTime endDate = DateTime.UtcNow - TimeSpan.FromDays(5); string end = endDate.ToString(AWSSDKUtils.ISO8601DateFormat); var request = new QueryRequest { TableName = "Reply", ReturnConsumedCapacity = "TOTAL", KeyConditionExpression = "Id = :v_replyId and ReplyDateTime between :v_start and :v_end", ExpressionAttributeValues = new Dictionary<string, AttributeValue> { {":v_replyId", new AttributeValue { S = replyId }}, {":v_start", new AttributeValue { S = start }}, {":v_end", new AttributeValue { S = end }} } }; var response = client.Query(request); Console.WriteLine("\nNo. of reads used (by query in FindRepliesPostedWithinTimePeriod) {0}", response.ConsumedCapacity.CapacityUnits); foreach (Dictionary<string, AttributeValue> item in response.Items) { PrintItem(item); } Console.WriteLine("To continue, press Enter"); Console.ReadLine(); } private static void FindRepliesInLast15DaysWithConfig(string forumName, string threadSubject) { Console.WriteLine("*** Executing FindRepliesInLast15DaysWithConfig() ***"); string replyId = forumName + "#" + threadSubject; DateTime twoWeeksAgoDate = DateTime.UtcNow - TimeSpan.FromDays(15); string twoWeeksAgoString = twoWeeksAgoDate.ToString(AWSSDKUtils.ISO8601DateFormat); var request = new QueryRequest { TableName = "Reply", ReturnConsumedCapacity = "TOTAL", KeyConditionExpression = "Id = :v_replyId and ReplyDateTime > :v_interval", ExpressionAttributeValues = new Dictionary<string, AttributeValue> { {":v_replyId", new AttributeValue { S = replyId }}, {":v_interval", new AttributeValue { S = twoWeeksAgoString }} }, // Optional parameter. ProjectionExpression = "Id, ReplyDateTime, PostedBy", // Optional parameter. ConsistentRead = true }; var response = client.Query(request); Console.WriteLine("No. of reads used (by query in FindRepliesInLast15DaysWithConfig) {0}", response.ConsumedCapacity.CapacityUnits); foreach (Dictionary<string, AttributeValue> item in response.Items) { PrintItem(item); } Console.WriteLine("To continue, press Enter"); Console.ReadLine(); } private static void FindRepliesForAThreadSpecifyOptionalLimit(string forumName, string threadSubject) { Console.WriteLine("*** Executing FindRepliesForAThreadSpecifyOptionalLimit() ***"); string replyId = forumName + "#" + threadSubject; Dictionary<string, AttributeValue> lastKeyEvaluated = null; do { var request = new QueryRequest { TableName = "Reply", ReturnConsumedCapacity = "TOTAL", KeyConditionExpression = "Id = :v_replyId", ExpressionAttributeValues = new Dictionary<string, AttributeValue> { {":v_replyId", new AttributeValue { S = replyId }} }, Limit = 2, // The Reply table has only a few sample items. So the page size is smaller. ExclusiveStartKey = lastKeyEvaluated }; var response = client.Query(request); Console.WriteLine("No. of reads used (by query in FindRepliesForAThreadSpecifyLimit) {0}\n", response.ConsumedCapacity.CapacityUnits); foreach (Dictionary<string, AttributeValue> item in response.Items) { PrintItem(item); } lastKeyEvaluated = response.LastEvaluatedKey; } while (lastKeyEvaluated != null && lastKeyEvaluated.Count != 0); Console.WriteLine("To continue, press Enter"); Console.ReadLine(); } private static void FindRepliesForAThread(string forumName, string threadSubject) { Console.WriteLine("*** Executing FindRepliesForAThread() ***"); string replyId = forumName + "#" + threadSubject; var request = new QueryRequest { TableName = "Reply", ReturnConsumedCapacity = "TOTAL", KeyConditionExpression = "Id = :v_replyId", ExpressionAttributeValues = new Dictionary<string, AttributeValue> { {":v_replyId", new AttributeValue { S = replyId }} } }; var response = client.Query(request); Console.WriteLine("No. of reads used (by query in FindRepliesForAThread) {0}\n", response.ConsumedCapacity.CapacityUnits); foreach (Dictionary<string, AttributeValue> item in response.Items) { PrintItem(item); } 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("************************************************"); } } }