【问题标题】:Java: Query DynamoDB table for all values for a Range key using MapperJava:使用 Mapper 在 DynamoDB 表中查询 Range 键的所有值
【发布时间】:2016-10-05 13:56:20
【问题描述】:

我有一个 DynamoDb 表。它的哈希键为“ID”,范围键为“Category”。

我正在尝试查找“类别”的所有条目,例如喜剧。

这是我的映射类:

@DynamoDBTable(tableName = "Videos")
public class VideoDynamoMappingAdapter {

    private String videoID;
    private String videoCategory;
    private String videoArtist;
    private String videoTitle;

    @DynamoDBHashKey(attributeName = "ID")
    public String getVideoID() {
        return videoID;
    }

    public void setVideoID(String videoID) {
        this.videoID = videoID;
    }
    @DynamoDBRangeKey(attributeName = "Category")
    public String getVideoCategory() {
        return videoCategory;
    }

    public void setVideoCategory(String videoCategory) {
        this.videoCategory = videoCategory;
    }

    @DynamoDBAttribute(attributeName = "ArtistName")
    public String getVideoArtist() {
        return videoArtist;
    }

    public void setVideoArtist(String videoArtist) {
        this.videoArtist = videoArtist;
    }

    @DynamoDBAttribute(attributeName = "VideoTitle")
    public String getVideoTitle() {
        return videoTitle;
    }

    public void setVideoTitle(String videoTitle) {
        this.videoTitle = videoTitle;
    }

}

我一直在尝试这样的查询:

    DynamoDBQueryExpression<VideoDynamoMappingAdapter> queryExpression = new DynamoDBQueryExpression<VideoDynamoMappingAdapter>()
            .withRangeKeyCondition()


    List<VideoDynamoMappingAdapter> itemList = mapper.query(VideoDynamoMappingAdapter.class, queryExpression);

我一直在看指南,但我看不懂,我原以为这是一个简单的查询,一直在做,所以也许我遗漏了一些东西:

http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/QueryingJavaDocumentAPI.html#DocumentAPIJavaQueryExample

提前感谢您的帮助

【问题讨论】:

    标签: java amazon-web-services amazon-dynamodb


    【解决方案1】:

    Notionquest 在他的回答中是正确的,即我无法在给定的范围条件下查询哈希键的所有值。我通过在我的 Category 属性上创建一个全局二级索引解决了这个问题。

    这是我的映射器类:

    @ DynamoDBTable(tableName = "AlarmTable")
    public class VideoDynamoMappingAdapter {
    
        private String videoID;
        private String videoCategory;
        private String videoArtist;
        private String videoTitle;
    
        @DynamoDBHashKey(attributeName = "ID")
        public String getVideoID() {
            return videoID;
        }
    
        public void setVideoID(String videoID) {
            this.videoID = videoID;
        }
    
        @DynamoDBIndexHashKey( globalSecondaryIndexName = "CategoryIndex", attributeName = "Category")
        public String getVideoCategory() {
            return videoCategory;
        }
    
        public void setVideoCategory(String videoCategory) {
            this.videoCategory = videoCategory;
        }
    
        @DynamoDBAttribute(attributeName = "VideoArtist")
        public String getVideoArtist() {
            return videoArtist;
        }
    
        public void setVideoArtist(String videoArtist) {
            this.videoArtist = videoArtist;
        }
    
        @DynamoDBAttribute(attributeName = "VideoTitle")
        public String getVideoTitle() {
            return videoTitle;
        }
    
        public void setVideoTitle(String videoTitle) {
            this.videoTitle = videoTitle;
        }
    
    }
    

    请注意关于类别的注释。

    然后我的查询是这样的:

    VideoDynamoMappingAdapter videosToFind = new VideoDynamoMappingAdapter();
            videosToFind.setVideoCategory("Other");
    
            DynamoDBQueryExpression<VideoDynamoMappingAdapter> queryExpression = new DynamoDBQueryExpression<VideoDynamoMappingAdapter>()
                    .withIndexName("CategoryIndex")
                    .withHashKeyValues(videosToFind)
                    .withConsistentRead(false);
    
            List<VideoDynamoMappingAdapter> itemList = mapper.query(VideoDynamoMappingAdapter.class, queryExpression);
            System.out.println("test" + itemList.size());
    

    我希望它对某人有所帮助。

    【讨论】:

      【解决方案2】:

      DynamoDB 表不能单独通过 Range 键查询,没有 Hash 键。但是不使用 Range 键,可以单独通过 Hash 键查询。

      当仅通过 Range 键查询 DynamoDB 表而不使用 Hash 键时,会抛出 ValidationException

      Unable to read item. Error JSON: {
        "message": "Query condition missed key schema element",
        "code": "ValidationException"
      }
      

      另一种选择是使用 Range 键扫描数据库。请注意,DynamoDB 扫描是一项代价高昂的操作,因为它会扫描整个表。

      按类别扫描视频表:-

      请注意,“OR” 条件用于“IN”,仅支持某些数据类型。

      public List<VideoDynamoMappingAdapter> getVidoesByCategory(String[] categories) {
      
              ScanResultPage<VideoDynamoMappingAdapter> videoResultPage = null;
              List<VideoDynamoMappingAdapter> videoList = new ArrayList<>();
      
              try {
      
                  do {
                      DynamoDBMapper dynamoDBMapper = new DynamoDBMapper(dynamoDBClient);
      
                      Map<String, AttributeValue> expressionAttributeValues = new LinkedHashMap<String, AttributeValue>();
      
                      StringBuilder filterExpression = new StringBuilder(); 
                      int i = 1;
      
                      for (String category : categories) {
                          if (i==1) {
                              filterExpression.append("Category = " + ":videoCategory" + i);  
                          } else {
                              filterExpression.append(" OR Category = " + ":videoCategory" + i);
                          }
      
                          expressionAttributeValues.put(":videoCategory" + i, new AttributeValue().withS(category));
                          i++;
                      }
      
                      System.out.println("Filterexpression =====>" + filterExpression.toString());
      
                      DynamoDBScanExpression scanExpression = new DynamoDBScanExpression()                
                              .withFilterExpression(filterExpression.toString())
                              .withExpressionAttributeValues(expressionAttributeValues);
      
                      if (videoResultPage != null) {
                          scanExpression.setExclusiveStartKey(videoResultPage.getLastEvaluatedKey());
                      }
      
                      videoResultPage = dynamoDBMapper.scanPage(VideoDynamoMappingAdapter.class, scanExpression);
      
                      System.out.println("Results ==========>" + videoResultPage.getResults());
      
                      videoList.addAll(videoResultPage.getResults());
      
                  } while (videoResultPage.getLastEvaluatedKey() != null);
      
              } catch (Exception db) {
      
                  db.printStackTrace();
      
              }
      
              System.out.println(videoList.toString());
              return videoList;
      
          }
      

      【讨论】:

      • 感谢您的回复。你能告诉我如何查询范围内的所有哈希吗?
      • 添加了扫码。正如我之前的回答中提到的,没有哈希键就无法查询。
      • 非常感谢您的回复。它表明我对文档的理解不正确。我不认为每次都扫描是一个好的选择,所以我将其更改为添加全局二级索引并对其进行查询。
      • 我可以请求您同时接受 gsi 和 this 的答案吗?目前没有一个被接受。
      • 我不能接受两个答案。因为问题是我如何查询。我会接受我的。我赞成你的。再次感谢您的帮助。
      猜你喜欢
      • 2014-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-27
      • 1970-01-01
      • 2021-07-25
      相关资源
      最近更新 更多