【问题标题】:Pagination in Dynamo db while scan operation扫描操作时 Dynamo db 中的分页
【发布时间】:2018-05-24 17:10:24
【问题描述】:

我想扫描我的 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 映射到我的域类时,我遇到了错误。

我是在误解 dynamodb 中的分页概念还是在代码中做错了什么。任何指导都将受到高度赞赏,因为我是新手。

【问题讨论】:

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


    【解决方案1】:
    1. 您只能通过 ExclusiveStartKey 从某个地方开始阅读。此键是表的主键。如果你知道你的 item 键,你可以这样使用它(例如你的表主键是 studentId):

      Map<String, AttributeValue> lastKeyEvaluated = new HashMap<String,AttributeValue>();
      lastKeyEvaluated.put("studentId", new AttributeValue(STUDENTID));
      
    2. 当您在 dynamo 中指定 limit = N 时,您正在设置它应该只从表中读取 N 个项目。在读取 N 个项目后应用任何过滤。见Limiting the Number of Items in the Result Set。 这可能会让你得到比预期更少的结果。因此,您可以在代码中创建一个变量来发送请求,直到您达到预期的限制并切断额外的结果。

      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
      
    3. Dynamo 使用它自己的 json 结构。见Dynamo response syntax。 您可以通过在 dynamo 中存储属性的方式获取属性的值。如果 studentId 是一个字符串,那么它可能是这样的:

      for (Map<String, AttributeValue> item : result.getItems()) {
          responseDomain = new ResponseDomain();
          responseDomain.setId(item.get("studentId").getS());
          domainList.add(responseDomain);
      }
      

    【讨论】:

      【解决方案2】:

      分页并不完全按照您的想法工作。

      使用 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 循环,以便一次处理一个页面,然后在准备好时检索下一页。

      【讨论】:

      • 在我的用例中我必须指定从哪里开始扫描表。为此,我是否必须先扫描整个表,然后在收到的项目上使用 for 循环来应用 start?
      • 扫描总是评估表中的每一项,没有办法设置起点。您可以使用过滤器表达式返回结果的子集。例如,如果您的项目属性为 1、2、3、4、5,您可以设置一个过滤器表达式以仅返回该属性值为 2-4 的结果。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-04-10
      • 2018-08-19
      • 1970-01-01
      • 2016-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多