扫描操作时Dynamo db中的分页

时间:2017-12-11 07:55:02

标签: json database amazon-web-services pagination amazon-dynamodb

我想扫描我的Dynamo数据库表并应用了分页功能。在我的请求中,我想从我希望分页的位置发送数字。说,例如我发送的请求有start = 3和limit = 10,其中start是我想扫描从表中的第三项开始,限制最多10项。但是限制我可以使用.withLimit()方法实现(我正在使用java)。我跟着this aws文件。以下是我想要实现的代码:

<Map<String, AttributeValue>> mapList = new ArrayList<>();
      AmazonDynamoDB client =AmazonDynamoDBClientBuilder.standard().build();

      Gson gson = new GsonBuilder().serializeNulls().create();

      Map<String, AttributeValue> expressionAttributeValues = new 
      HashMap<String,AttributeValue>(); 
      expressionAttributeValues.put(":name",
      newAttributeValue().withS(name));

      List<ResponseDomain> domainList = new ArrayList<>(); 
      ResponseDomain responseDomain = null;

      //lastKeyEvaluated = start
      Map<String, AttributeValue> lastKeyEvaluated = null; 
      do { 
      ScanRequest scanRequest = new 
      ScanRequest().withTableName(STUDENT_TABLE)
      .withProjectionExpression("studentId, studentName")
      .withFilterExpression("begins_with(studentName, :name)")
      .withExpressionAttributeValues(expressionAttributeValues).
      withExclusiveStartKey(lastKeyEvaluated);

      ScanResult result = client.scan(scanRequest);

      for (Map<String, AttributeValue> item : result.getItems()) { 
      responseDomain = gson.fromJson(gson.toJson(item), 
      ResponseDomain.class); 
      domainList.add(responseDomain);


      } lastKeyEvaluated = result.getLastEvaluatedKey(); 
      } while (lastKeyEvaluated!= null); 
      //lastKeyEvaluated = size

      return responseDomain;

在上面的代码中我被困在3个地方:

  1. 如何将lastKeyEvaluated设置为我的起始值,即3
  2. 在while条件下如何指定我的限制,即10
  3. 当我尝试将项目从Json映射到我的域类时,我遇到错误。
  4. 我是否误解了dynamodb中的分页概念或在代码中做错了什么。任何指导都将受到高度赞赏,因为我是新手。

2 个答案:

答案 0 :(得分:4)

  1. 您只能通过 ExclusiveStartKey 从某个地方开始阅读。此键是表的主键。如果您知道自己的商品密钥,则可以像这样使用它(例如,您的表主键是 studentId ):

    sand rock needed to be mixed and shaked well before using it for construction work
    
  2. 当你在发电机中指定 limit = N 时,你设置它应该只从表中读取 N 项。读取 N 项后应用任何过滤。见Limiting the Number of Items in the Result Set。 这可能会让您的结果比预期的要少。因此,您可以在代码中创建一个变量来发送请求,直到达到预期的限制并切断额外的结果。

    Map<String, AttributeValue> lastKeyEvaluated = new HashMap<String,AttributeValue>();
    lastKeyEvaluated.put("studentId", new AttributeValue(STUDENTID));
    
  3. Dynamo使用它自己的json结构。见Dynamo response syntax。 您可以按照在dynamo中存储属性的方式获取属性的值。如果 studentId 是一个字符串,那么它可能是这样的:

    int N = 10;
    List<Map<String, AttributeValue>> itemsList = new ArrayList<>();
    do {
       // scanRequest.withLimit(N)
    
       ...
    
       itemList.addAll(result.getItems());
    
       if(itemsList.size() >= N) {
           itemsList = itemsList.subList(0, N);
           break;
       }
    } while (lastKeyEvaluated != null && itemsList.size() < N);
    
    // process the itemsList
    

答案 1 :(得分:1)

分页并不像你想象的那样有效。

使用ScanRequest.withLimit(X)选择每页结果中的项目数。例如,设置ScanRequest.withLimit(10)意味着您获得的每个结果页面中都有10个项目。

lastKeyEvaluated不是页面的数字,它是表格中项目的实际键。具体来说,它是您检索的最后一组结果中最后一项的关键。

这样想。想象一下你的结果是:

Dog
Chicken
Cat
Cow
Rhino
Buffalo

现在让我说我做了ScanRequest.withLimit(2)和lastKeyEvaluated = null,所以每个结果页面都有2个项目,我将检索第一页结果。我的第一次扫描返回

Dog
Chicken

并且

lastKeyEvaluated = result.getLastEvaluatedKey();

返回

Chicken

现在要获得下一页结果,我会使用ScanRequest.withExclusiveStartKey(Chicken)。下一组结果将是

Cat
Cow

上面的代码使用do / while循环来检索结果的每一页并将其打印出来。很可能你会想要删除那个do / while循环,这样你就可以一次处理一个页面,然后在准备好后检索下一页。