通过Boto3进行DynamoDB分页,不存在NextToken,但存在LastEvaluatedKey吗?

时间:2019-05-27 14:46:50

标签: pagination amazon-dynamodb boto3

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密钥,但不包括吗?

{'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

1 个答案:

答案 0 :(得分: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”。