从Boto DynamoDB Scan中的迭代器对象解包不确定数量的属性

时间:2015-07-13 16:38:30

标签: python iterator generator amazon-dynamodb boto

所以我使用的是AWS DynamoDB,因为它具有NoSQL-ness功能,并且能够使用不明确数量的列#39;可以这么说。为此,我使用boto与数据库进行交互,但是动态地获取不同数量的列/属性证明是困难的。

我的db表大多没有确定的模式(为什么我要使用NoSQL),并且大多数行的属性与其他行不同。我知道Dynamo可以做到这一点,但我需要一种方法来通过简单的扫描获得所有键/列/属性。我的数据库并不大,根本不会增长太多,所以我并不担心扫描/查询的效率。

我的桌子(或多或少):

{'name': 'John',    'email': '12@34.com'}
{'name': 'Charlie', 'email': '34@56.com', 'dislikes': 'people's knees'}
{'name': 'Joe',     'email': '78@90.com', 'hobby':    'golf'}

如您所见,每行有不同的属性。

我的boto测试脚本

import os
import boto.dynamodb2
from boto.dynamodb2.table import Table

AWS_ACCESS_KEY_ID = os.getenv("AWS_ACCESS_KEY_ID")
AWS_SECRET_ACCESS_KEY = os.getenv("AWS_SECRET_ACCESS_KEY")


def connect():
    conn = boto.dynamodb2.connect_to_region(
        'us-east-1',
        aws_access_key_id=AWS_ACCESS_KEY_ID,
        aws_secret_access_key=AWS_SECRET_ACCESS_KEY)
    return conn

conn = connect()

table = Table('table1', connection=conn)

scan = table.scan()

这将返回一个迭代器对象

<boto.dynamodb2.items.Item object at ....>

要解析这个对象,必须知道属性名称,并且不能用数字索引对象:

for i in scan:
    print i['name']
    # John
    # Charlie
    # Joe

for i in scan:
    print i[0]
    # None
    # None
    # None

当我使用多个变量进行解包时,它可以工作,但我必须像这样定义变量:

for i, j, k in scan:
        print i, j, k

适用于有三列但只有三列的行。

我希望能够做的是遍历每一行并返回其相应的列,这可能与下一行不同。我碰到了墙,任何反馈都非常感激。

1 个答案:

答案 0 :(得分:0)

发现了问题!

所以我感到非常愚蠢。这个答案的关键部分是扫描时调用的.items()。这使得扫描实际上可以按照我想要的方式进行迭代。

我想要一本不同大小字典的字典,所以我需要创建一个更宽的字典来保存每一行/每个人和一个更窄的范围来添加每个细节(键/列及其值)。您的数据结构可能与我的不同,但这有望让您指向正确的方向。

...

scan = table.scan()

#outer-most dict for each row
dict0 = {}

# enumerate so each row can be appended to dict0 using index 
for index, row in enumerate(scan):
    # inner-most dict for each key/value pair
    dict1 = {}
    for key, value in row.items():
        dict1[str(key)] = str(value)
    dict0[index] = dict1

我使用了str()因为我得到了unicode u&#39; &#39;我的结果中的字符。

迭代数据大致相同,我们只是遗漏了字典。

for index, keyValues in dict0.items():
    print index
    for key, value in keyValues.items():
        print "\t {}: {}".format(key, value)

打印出类似的内容(按时间添加排序):

0
    "hobby": "golf"
    "email": "78@90.com"
    "name" : "Joe"
1
    'dislikes': "people's knees"
    "name" : "Charlie"
    "email": "34@56.com"
2
    "name" : "John"
    "email": "12@34.com"