簡體   English   中英

DynamoDB 表分區鍵和排序鍵是 1:1 - 如何僅使用分區鍵進行查詢?

[英]DynamoDB Table Partition key and sort key are 1:1 - how to go about querying only using partition key?

我正在嘗試查詢具有分區鍵和排序鍵的表(但是分區鍵和排序鍵是 1:1,我只想使用分區鍵進行查詢 [其中只會返回一個項目])。

        QueryRequest query = new QueryRequest()
            .withTableName(TABLE_NAME)
            .withKeyConditionExpression("testId = :" + "1234567890");

    QueryResult result = client.query(query);

這是我試過的代碼,但是沒有用(testId是分區鍵名,1234567890是String形式的分區鍵值); 你們都知道我可以使用僅使用分區鍵進行查詢的方法嗎,請記住,由於分區鍵和排序鍵是 1:1,因此只會返回一個項目? 非常感謝你。 [這是我的第一篇 Stack Overflow 帖子——如果我措辭不佳,我深表歉意,我很樂意回答有關我措辭的任何問題]

僅供參考:這是我在嘗試使用上面的代碼時得到的錯誤聲明:

errorMessage": "Invalid KeyConditionExpression: An expression attribute value used in expression is not defined

您確實應該更新以使用適用於 Java V2 的 WS開發工具包(使用適用於 V1 的 AWS 開發工具包不是最佳實踐)。 使用 AWS SDK for Java v2 是使用 Amazon DynamoDB API 的最佳實踐。

要了解有關 AWS V2 Java API 的更多信息,請在此處閱讀開發人員指南。

開發人員指南 - 適用於 Java 2.x 的 AWS 開發工具包

現在我將用 V2 來回答這個問題。 對我有用的解決方案是創建一個名為year-index的二級索引。 這僅使用我名為year的分區鍵(並且不使用排序鍵)。

我可以使用此索引成功查詢,如此處所示使用AWS 管理控制台

現在只返回 2014 年的電影。 當您的表具有由分區鍵和排序鍵組成的復合鍵並且您只想查詢分區鍵時,這就是您的查詢方式。

順便說一句 - 你說你有一個二級索引。 一個表可以有超過 1 個二級索引

在此處輸入圖像描述

V2 查詢二級索引所需的代碼

我將向您展示如何使用 V2 使用三種方式搜索二級索引。

第一種方式 - 使用 V2 增強客戶端創建二級索引后,您可以使用它進行查詢。 如前所述,我創建了一個名為year-index的二級索引。 我可以通過DynamoDB Enhanced Client使用這個二級索引來查詢數據。

因為,我正在查詢Movies表,所以我必須像這樣創建一個名為Movies的類。 注意@DynamoDbSecondaryPartitionKey注釋的使用。

package com.example.dynamodb;

import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSecondaryPartitionKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSortKey;

@DynamoDbBean
public class Movies {
    private String title;
    private int year;
    private String info;

    @DynamoDbSecondaryPartitionKey(indexNames = { "year-index" })
    @DynamoDbPartitionKey
    public int getYear() {
      return this.year;
    }
    public void setYear(int year) {
        this.year = year;
    }

    @DynamoDbSortKey
    public String getTitle() {
        return this.title;
    }
    public void setTitle(String title) {
        this.title = title;
    }

    public String getInfo() {
        return this.info;
    }

    public void setInfo(String info) {
        this.info = info;
    }
}

最后,這里是 V2 代碼,可讓您使用二級索引進行查詢。

package com.example.dynamodb;

// snippet-start:[dynamodb.java2.get_item_index.import]

import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
import software.amazon.awssdk.core.pagination.sync.SdkIterable;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbIndex;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable;
import software.amazon.awssdk.enhanced.dynamodb.Key;
import software.amazon.awssdk.enhanced.dynamodb.TableSchema;
import software.amazon.awssdk.enhanced.dynamodb.model.Page;
import software.amazon.awssdk.enhanced.dynamodb.model.QueryConditional;
import software.amazon.awssdk.enhanced.dynamodb.model.QueryEnhancedRequest;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;

import java.util.List;
// snippet-end:[dynamodb.java2.get_item_index.import]


/**
 * Before running this Java V2 code example, set up your development environment, including your credentials.
 *
 * For more information, see the following documentation topic:
 *
 * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html
 *
 * To get an item from an Amazon DynamoDB table using the AWS SDK for Java V2, its better practice to use the
 * Enhanced Client, see the EnhancedGetItem example.
 *
 *  Create the Movies table by running the Scenario example and loading the Movies data from the JSON file. Next create a secondary
 *  index for the Movies table that uses only the year column. Name the index **year-index**. For more information, see:
 *
 * https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSI.html
 */
public class EnhancedGetItemUsingIndex {

        public static void main(String[] args) {

                String tableName = "Movies" ; //args[0];
                ProfileCredentialsProvider credentialsProvider = ProfileCredentialsProvider.create();
                Region region = Region.US_EAST_1;
                DynamoDbClient ddb = DynamoDbClient.builder()
                        .credentialsProvider(credentialsProvider)
                        .region(region)
                        .build();

                queryIndex(ddb, tableName);
                ddb.close();
        }

        // snippet-start:[dynamodb.java2.get_item_index.main]
        public static void queryIndex(DynamoDbClient ddb, String tableName) {

                try {
                        // Create a DynamoDbEnhancedClient and use the DynamoDbClient object.
                        DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder()
                                .dynamoDbClient(ddb)
                                .build();

                        //Create a DynamoDbTable object based on Movies.
                        DynamoDbTable<Movies> table = enhancedClient.table("Movies", TableSchema.fromBean(Movies.class));
                        String dateVal = "2013";

                        DynamoDbIndex<Movies> secIndex =
                                enhancedClient.table("Movies", TableSchema.fromBean(Movies.class))
                                        .index("year-index");

                        AttributeValue attVal = AttributeValue.builder()
                                .n(dateVal)
                                .build();

                        // Create a QueryConditional object that's used in the query operation.
                        QueryConditional queryConditional = QueryConditional
                                .keyEqualTo(Key.builder().partitionValue(attVal)
                                        .build());

                        // Get items in the table.
                        SdkIterable<Page<Movies>> results =  secIndex.query(
                                QueryEnhancedRequest.builder()
                                        .queryConditional(queryConditional)
                                        .limit(300)
                                        .build());

                        //Display the results.
                        results.forEach(page -> {
                                List<Movies> allMovies =  page.items();
                                for (Movies myMovies: allMovies) {
                                        System.out.println("The movie title is " + myMovies.getTitle() + ". The year is " + myMovies.getYear());
                                }
                        });

                } catch (DynamoDbException e) {
                        System.err.println(e.getMessage());
                        System.exit(1);
                }
        }

        // snippet-end:[dynamodb.java2.get_item_index.main]
}

現在,這將返回年份為 2013 年的所有電影。

在此處輸入圖像描述

第二種方式 - 使用 V2 服務客戶端

package com.example.dynamodb;

// snippet-start:[dynamodb.java2.query_items_sec_index.import]
import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.model.QueryRequest;
import software.amazon.awssdk.services.dynamodb.model.QueryResponse;
import java.util.HashMap;
import java.util.Map;
// snippet-end:[dynamodb.java2.query_items_sec_index.import]


/**
 * Before running this Java V2 code example, set up your development environment, including your credentials.
 *
 * For more information, see the following documentation topic:
 *
 * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html
 *
 * Create the Movies table by running the Scenario example and loading the Movies data from the JSON file. Next create a secondary
 * index for the Movies table that uses only the year column. Name the index **year-index**. For more information, see:
 *
 * https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSI.html
 */
public class QueryItemsUsingIndex {

        public static void main(String[] args) {

                String tableName = "Movies" ; //args[0];
                ProfileCredentialsProvider credentialsProvider = ProfileCredentialsProvider.create();
                Region region = Region.US_EAST_1;
                DynamoDbClient ddb = DynamoDbClient.builder()
                        .credentialsProvider(credentialsProvider)
                        .region(region)
                        .build();

                queryIndex(ddb, tableName);
                ddb.close();
        }

        // snippet-start:[dynamodb.java2.query_items_sec_index.main]
        public static void queryIndex(DynamoDbClient ddb, String tableName) {

                try {
                        Map<String,String> expressionAttributesNames = new HashMap<>();
                        expressionAttributesNames.put("#year","year");

                        Map<String, AttributeValue> expressionAttributeValues = new HashMap<>();
                        expressionAttributeValues.put(":yearValue", AttributeValue.builder().n("2013").build());

                        QueryRequest request = QueryRequest.builder()
                                .tableName(tableName)
                                .indexName("year-index")
                                .keyConditionExpression("#year = :yearValue")
                                .expressionAttributeNames(expressionAttributesNames)
                                .expressionAttributeValues(expressionAttributeValues)
                                .build();

                        System.out.println("=== Movie Titles ===");

                        QueryResponse response = ddb.query(request);
                        response.items()
                                .forEach(movie-> System.out.println(movie.get("title").s()));


                } catch (DynamoDbException e) {
                        System.err.println(e.getMessage());
                        System.exit(1);
                }
        }
        // snippet-end:[dynamodb.java2.query_items_sec_index.main]
}

**第三種方式 - 使用 PartQL

當然,您可以使用 PartiQL 查詢分區鍵。 例如。

public static void queryTable(DynamoDbClient ddb) {
        String sqlStatement = "SELECT * FROM MoviesPartiQ where year = ? ORDER BY info";
        try {

            List<AttributeValue> parameters = new ArrayList<>();
            AttributeValue att1 = AttributeValue.builder()
                    .n(String.valueOf("2013"))
                    .build();
            parameters.add(att1);

            // Get items in the table and write out the ID value.
            ExecuteStatementResponse response = executeStatementRequest(ddb, sqlStatement, parameters);
            System.out.println("ExecuteStatement successful: "+ response.toString());

        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM