2016-12-06 4 views
0

"userId"にグローバルセカンダリインデックスを持つ "product"という名前のDynamoDBテーブルがあります。プライマリキーは "id"です。 "userID" GSIで "withExclusiveStartKey"を使用してページネーションを使用してクエリを実装しようとしています。私は、有効なlastIdを渡すとき はしかし、私は例外を以下の取得:AmazonDynamoDBv2;ステータスコード:DyanmoDB:グローバルセカンダリインデックスのwithExclusiveStartKeyを使用したページ分割

独占スタートキーは、テーブルのキースキーマ (サービスとして同じサイズでなければなりません400;エラーコード: にValidationException;リクエストID: 822db97e-04a3-4c36-8c72-6008e2693679)

は、私はここで間違って何をしているのですか?

public QueryResultPage<Product> findPaged(String userId,int limit,String lastId) { 
     DynamoDBMapper mapper = new DynamoDBMapper(dynamoDb);  
     Map<String, AttributeValue> vals = new HashMap<>(); 
     vals.put(":valUserId", new AttributeValue().withS(userId)); 
       DynamoDBQueryExpression<Product> queryExp = new   DynamoDBQueryExpression<Product>() 
       .withKeyConditionExpression("userId = :valUserId") 
       .withIndexName(ModelConsts.TBL_PRODUCT_GSI_USERID) 
       .withExpressionAttributeValues(vals) 
       .withScanIndexForward(false) 
       .withConsistentRead(false) 
       .withLimit(limit); 
      if (lastId != null) {//paging 
      Map<String, AttributeValue> exclusiveStartKey = new HashMap<String, AttributeValue>(); 
        exclusiveStartKey.put("id", new AttributeValue().withS(lastId)); 
       queryExp = queryExp.withExclusiveStartKey(exclusiveStartKey); 
     } 
     QueryResultPage<Product> result = mapper.queryPage(Product.class, queryExp); 
     return result;  
    } 

答えて

1

GSIの元のテーブルのすべてのキー値を開始キーに設定する必要があります。表にパーティション・キーとソート・キーがある場合は、両方のキー値を開始キー値として設定する必要があります。以下の例で

は: -

1)videosテーブルは、ASソートキーパーティションキーとしてvideoidcategoryを有する

2)GSIは、パーティションキーとしてcategoryvideoidとしてソートで定義されキー

以下のコードは、開始キーが設定されたcategory値(つまり、パーティションとソートキーの両方)でGSIに照会します。

パーティションやソートキーにデータを入力しなかったときにエラーを再現できます。

サンプルコード: -

public QueryResultPage<VideoDynamoMappingAdapter> findVideosByCategoryUsingGSIAndMapperWithStartKey(
     String category) { 
    DynamoDBMapper dynamoDBMapper = new DynamoDBMapper(dynamoDBClient); 
    QueryResultPage<VideoDynamoMappingAdapter> queryResult = null; 
    Map<String, AttributeValue> vals = new HashMap<>(); 
    vals.put(":val1", new AttributeValue().withS(category)); 
    DynamoDBQueryExpression<VideoDynamoMappingAdapter> queryExp = new DynamoDBQueryExpression<VideoDynamoMappingAdapter>() 
      .withKeyConditionExpression("category = :val1").withIndexName("VideoCategoryGsi") 
      .withExpressionAttributeValues(vals).withScanIndexForward(false).withConsistentRead(false).withLimit(1); 

    Map<String, AttributeValue> startKey = new HashMap<>(); 

    startKey.put("videoid", new AttributeValue().withS("2")); 
    startKey.put("category", new AttributeValue().withS("Thriller")); 

    queryExp.setExclusiveStartKey(startKey); 

    queryResult = dynamoDBMapper.queryPage(VideoDynamoMappingAdapter.class, queryExp); 

    System.out.println("Result size ===>" + queryResult.getResults().size()); 
    System.out.println("Last evaluated key ===>" + queryResult.getLastEvaluatedKey()); 

    for (VideoDynamoMappingAdapter videoDynamoMappingAdapter : queryResult.getResults()) { 
     System.out.println("Video data ===>" + videoDynamoMappingAdapter.toString()); 
    } 

    return queryResult; 

} 
3

私はGSIクエリのために、手動でをexclusiveStartKeyを構築しようとするあなたの人々のために、この答えを書いています。キー

  • キーテーブルが
  • これはいないようです

    • GSIハッシュキー、
    • GSI範囲:排他的なスタートキーが3つのコンポーネントから構成されていることが表示されます返品されたlastEvaluatedKeyを電話番号:

      setLastEvaluatedKey(queryResult.getLastEvaluatedKey()); 
      

      答えは正しいですが、私の場合は助けにならなかったキーに2つのコンポーネントしかないという印象を読者に残します。 ここに記載されている解決策は、最初にthis GitHub issueに記載されています。

    関連する問題