【问题标题】:DynamoDB Pagination via Boto3, NextToken is not present but LastEvaluatedKey is?通过 Boto3 进行 DynamoDB 分页,NextToken 不存在,但 LastEvaluatedKey 存在?
【发布时间】:2019-10-13 03:49:45
【问题描述】:

boto3 和 dynamodb 分页器的文档指定在分页时应返回 NextToken,然后您将在下一个查询中包含该令牌,以让 StartingToken 恢复分页会话(通过 RESTful API 访问信息时会发生这种情况)。

但是,我的测试表明它不会在结果中返回 NextToken,而是返回 LastEvaluatedKey。我在想我可以使用 LastEvaluatedKey 作为令牌,但这不起作用?

paginator = client.get_paginator('scan')
page_iterator = paginator.paginate(TableName='test1', PaginationConfig={'PageSize': 1 , 'MaxItems': 5000,  'MaxSize': 1 })

    for page in page_iterator:
        print(page)
        break   

我希望从 page_iterator 返回的页面对象包含 NextToken Key 但它没有?

{'Items': [{'PK': {'S': '99'}, 'SK': {'S': '99'}, 'data': {'S': 'Test Item 99'}}], 'Count': 1, 'ScannedCount': 1, 'LastEvaluatedKey': {'PK': {'S': '99'}, 'SK': {'S': '99'}}, 'ResponseMetadata': {'RequestId': 'DUE559L8KVKVH8H7G0G2JH0LUNVV4KQNSO5AEMVJF66Q9ASUAAJG', 'HTTPStatusCode': 200, 'HTTPHeaders': {'server': 'Server', 'date': 'Mon, 27 May 2019 14:22:09 GMT', 'content-type': 'application/x-amz-json-1.0', 'content-length': '153', 'connection': 'keep-alive', 'x-amzn-requestid': 'DUE559L8KVKVH8H7G0G2JH0LUNVV4KQNSO5AEMVJF66Q9ASUAAJG', 'x-amz-crc32': '3759060959'}, 'RetryAttempts': 0}}

我错过了什么?

更新:不知何故与此有关? How to use Boto3 pagination

【问题讨论】:

  • 当你让 page_iterator 遍历页面时为什么需要令牌?
  • 因为我将此页数据返回给 HTTP API 客户端。我还需要返回该令牌,以便他们可以返回并在后续请求中获取下一页。

标签: pagination amazon-dynamodb boto3


【解决方案1】:

有几种方法可以使用 boto3 扫描分页器解决此问题。

第一个选项是像这样调用build_full_result

result = paginator.paginate(TableName="your_table", PaginationConfig={"MaxItems":10, "PageSize": 10}).build_full_result()

这将返回一个包含 10 个项目的响应,如果项目超过 10 个,则会填充“NextToken”。这可能是最简单的方法,您可以将 MaxItems 视为您返回的页面大小,如果“NextToken”为空,则您处于扫描结束时。

我注意到,如果您不指定页面大小,结果是相同的,但消耗的容量和“ScannedCount”会更高。

另一种方法是直接使用botocore.paginate中的TokenEncoder对'StartingToken'进行编码。

如果对分页器的初始调用是这样的:

pagination_config = {
    "MaxItems": 5000,
    "PageSize": 10,
}

scan_iterator = scan_paginator.paginate(
    TableName="your_table_name",
    PaginationConfig=pagination_config
)

分页结果将如问题所述。前 10 个结果将在第一页返回,并且未指定“NextToken”,但指定了“LastEvaluatedKey”。

要使用它,请将返回的“LastEvaluatedKey”编码为“ExclusiveStartKey”,并将其作为“StartingToken”传递到分页配置中。

from botocore.paginate import TokenEncoder
encoder = TokenEncoder()
for page in scan_iterator:
    if "LastEvaluatedKey" in page:
            encoded_token = encoder.encode({"ExclusiveStartKey": page["LastEvaluatedKey"]})

然后:

pagination_config = {
    "MaxItems": 500,
    "PageSize": 10,
    "StartingToken": encoded_token
}

将主键编码为“ExclusiveStartKey”的原因是它是actual scan API 所期望的。本质上,分页器将“LastEvaluatedKey”和“ExclusiveStartKey”编码/解码为“NextToken”和“StartingToken”值。如果您对执行build_full_result 时返回的“NextToken”进行 base64 解码,您会发现它也使用了“ExclusiveStartKey”。

【讨论】:

  • 谢谢。我最终只是没有使用 Pagination API,只是抓取 LastEvaluatedKey base64 对其进行编码,然后允许在后续调用中将其传回。所以,虽然我并没有真正分页,但我认为它可以更有效地使用,并且浪费的读取次数会更少。
猜你喜欢
  • 1970-01-01
  • 2017-01-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-21
  • 2018-10-31
  • 2019-10-02
  • 2017-08-03
相关资源
最近更新 更多