使用boto3完成对dynamoDB的完整扫描。
使用boto3完成对dynamoDB的完整扫描。
我的表格大约有220MB,其中包含250,000条记录。我想将所有数据导入Python。我意识到这需要一个分批处理的过程,并且需要循环遍历,但我不确定如何设置批次从上一批次结束的地方开始。\n有没有办法过滤我的扫描?根据我所读的,过滤发生在加载之后,加载在1MB处停止,所以我实际上无法扫描新对象。\n任何帮助将不胜感激。\n
import boto3 dynamodb = boto3.resource('dynamodb', aws_session_token = aws_session_token, aws_access_key_id = aws_access_key_id, aws_secret_access_key = aws_secret_access_key, region_name = region ) table = dynamodb.Table('widgetsTableName') data = table.scan()
问题的原因是boto3的paginators在处理DynamoDB的扫描操作时返回的数据格式不符合预期。解决方法是使用TypeDeserializer来转换数据类型。
boto3是一个Python的AWS SDK,提供了许多用于操作Amazon Web Services的功能。其中包括对DynamoDB的操作。在处理DynamoDB的扫描操作时,boto3提供了一个Paginator类来处理分页的细节,方便用户进行数据的遍历操作。
具体的使用方法如下:
import boto3 client = boto3.client('dynamodb') paginator = client.get_paginator('scan') for page in paginator.paginate(): # do something
上述代码中,首先导入boto3库,并创建一个DynamoDB的client对象。然后通过client对象的get_paginator方法创建一个Paginator对象,指定操作为scan。接下来使用Paginator对象的paginate方法进行分页操作,遍历每一页的数据进行处理。
需要注意的是,由于Paginator类是通用的,返回的数据格式可能不符合预期。每个DynamoDB的item都以字典的形式返回,其格式为type: value,例如{'myAttribute': {'M': {}}, 'yourAttribute': {'N': u'132457'}}。其中,'M'表示一个空map,'N'表示一个数值类型(以字符串形式返回,需要转换为数值类型)。其他类型,如字符串、map和布尔值,会被boto3转换为对应的Python类型。
原帖中还提到了一个问题,就是Paginator返回的数据中包含了一些无关的元数据,这使得数据处理起来变得困难。原帖的作者考虑切换到使用DynamoDB的resource而非client,并使用LastEvaluatedKey来进行分页操作,这样可以避免处理Paginator返回的数据。
不过,原帖的作者在后来发现了一个解决方法,即使用TypeDeserializer类来转换数据类型。TypeDeserializer是boto3提供的一个辅助类,可以将DynamoDB的item转换为Python对象。作者在stackoverflow上找到了一个示例代码,链接如下:stackoverflow.com/a/46738251/923817。
最后,原帖中还有其他用户对此问题的回复,其中某些情况下自己最近在使用Clojure开发,在处理Amazon的API时遇到的问题要少得多。这说明虽然boto3提供了便捷的操作接口,但在处理DynamoDB的扫描操作时仍然存在一些不便之处。
问题的出现的原因是DynamoDB的scan
方法对每次扫描的数据限制为1MB。这意味着如果表中的数据超过1MB,一次扫描将无法返回所有的数据。
为了解决这个问题,可以使用LastEvaluatedKey
来获取DynamoDB表中的所有数据。上述代码提供了一个示例循环,使用LastEvaluatedKey
来获取表中的所有数据,并将结果存储在一个列表中。
具体解决方法如下:
1. 导入boto3库,创建DynamoDB的客户端对象。
import boto3 client = boto3.client('dynamodb')
2. 创建一个函数dump_table
,并传入表名作为参数。
def dump_table(table_name):
3. 初始化一个空列表results
用于存储所有的数据。
results = []
4. 初始化一个变量last_evaluated_key
,用于存储上一次扫描的最后一个键。
last_evaluated_key = None
5. 使用循环来不断扫描表中的数据,直到所有数据都被获取。
while True:
6. 判断last_evaluated_key
是否存在,如果存在,则使用scan
方法扫描表,并设置ExclusiveStartKey
参数为上一次扫描的最后一个键。
if last_evaluated_key:
response = client.scan(TableName=table_name, ExclusiveStartKey=last_evaluated_key)
7. 如果last_evaluated_key
不存在,则使用scan
方法扫描表。
else:
response = client.scan(TableName=table_name)
8. 获取扫描结果中的LastEvaluatedKey
,并更新last_evaluated_key
的值。
last_evaluated_key = response.get('LastEvaluatedKey')
9. 将扫描结果中的Items
添加到results
列表中。
results.extend(response['Items'])
10. 判断last_evaluated_key
是否为空,如果为空,则跳出循环。
if not last_evaluated_key:
break
11. 返回最终的结果列表results
。
return results
12. 使用dump_table
函数来获取表中的所有数据,并将结果存储在data
变量中。
data = dump_table('your-table-name')
13. 最后,可以对获取到的数据data
进行后续处理。
完整扫描 DynamoDB 并使用 boto3 的原因及解决方法
在使用 boto3 进行 DynamoDB 的扫描操作时,可能会遇到需要完整扫描整个表的情况。以下是一个关于如何处理这种情况的问题的原因和解决方法。
根据 Amazon DynamoDB 文档,关于表扫描的回答了你的问题。
简而言之,需要在响应中检查 LastEvaluatedKey
。以下是使用你的代码的示例:
import boto3 dynamodb = boto3.resource('dynamodb', aws_session_token=aws_session_token, aws_access_key_id=aws_access_key_id, aws_secret_access_key=aws_secret_access_key, region_name=region ) table = dynamodb.Table('widgetsTableName') response = table.scan() data = response['Items'] while 'LastEvaluatedKey' in response: response = table.scan(ExclusiveStartKey=response['LastEvaluatedKey']) data.extend(response['Items'])
虽然这段代码可以工作,但是需要注意 boto3 文档 中的说明:如果 LastEvaluatedKey 为空,则表示已处理完“最后一页”的结果,没有更多数据可获取。 所以我使用的测试条件是 while response.get('LastEvaluatedKey')
而不是 while 'LastEvaluatedKey' in response
,因为“为空”并不一定意味着“不存在”,这种方法在任何情况下都有效。
另外,使用 paginator 是更方便的遍历查询/扫描项目的方式。
response.get('LastEvaluatedKey')
我得到了 None
,无法将它应用于 while
循环。
_J 提供了另一种解决方法,可以使用 while True:
,然后使用 if not response.get('LastEvaluatedKey'): break
或类似的方法。你还可以将处理过程封装在一个函数中,调用该函数,然后使用上面的 while response.get(...):
来调用函数以处理后续页面。基本上,你只需要模拟 Python 中并不存在的 do... while
循环。
为什么不使用 while response.get('LastEvaluatedKey', False)
?
这样也可以工作,但并不必要。.get 默认情况下会返回 None,如果请求的键不存在,则 None 会被转换为 False。可以通过运行 bool({}.get('test'))
来确认这一点。
以上是关于如何解决完整扫描 DynamoDB 表的问题的原因和解决方法。