使用Python/Boto更新DynamoDB原子计数器

Jas*_*igh 9 python counter atomic boto amazon-dynamodb

我正在尝试使用Python Boto 2.3.0更新原子计数计数器,但是找不到该操作的文档.

似乎没有直接接口,所以我尝试使用layer1接口进行"原始"更新,但我甚至无法完成简单的更新.

我尝试了以下变化,但都没有运气

dynoConn.update_item(INFLUENCER_DATA_TABLE, 
                     {'HashKeyElement': "9f08b4f5-d25a-4950-a948-0381c34aed1c"}, 
                     {'new': {'Value': {'N':"1"}, 'Action': "ADD"}})    

dynoConn.update_item('influencer_data', 
                     {'HashKeyElement': "9f08b4f5-d25a-4950-a948-0381c34aed1c"}, 
                     {'new': {'S' :'hello'}})                                 

dynoConn.update_item("influencer_data", 
                     {"HashKeyElement": "9f08b4f5-d25a-4950-a948-0381c34aed1c"},
                     {"AttributesToPut" : {"new": {"S" :"hello"}}})      
Run Code Online (Sandbox Code Playgroud)

它们都会产生相同的错误:

  File "/usr/local/lib/python2.6/dist-packages/boto-2.3.0-py2.6.egg/boto/dynamodb/layer1.py", line 164, in _retry_handler
    data)
boto.exception.DynamoDBResponseError: DynamoDBResponseError: 400 Bad Request
{u'Message': u'Expected null', u'__type': u'com.amazon.coral.service#SerializationException'}
Run Code Online (Sandbox Code Playgroud)

我还在这里调查了API文档,但它们非常简洁.

我做了很多搜索和摆弄,我唯一剩下的就是使用PHP API并深入研究代码以找到它"格式化"JSON主体的位置,但这有点痛苦.请救我脱离这种痛苦!

gar*_*aat 12

对不起,我误解了你在找什么.您可以通过layer2完成此操作,尽管有一个小错误需要解决.这是一些Layer2代码:

>>> import boto
>>> c = boto.connect_dynamodb()
>>> t = c.get_table('counter')
>>> item = t.get_item('counter')
>>> item
{u'id': 'counter', u'n': 1}
>>> item.add_attribute('n', 20)
>>> item.save()
{u'ConsumedCapacityUnits': 1.0}
>>> item  # Here's the bug, local Item is not updated
{u'id': 'counter', u'n': 1}
>>> item = t.get_item('counter')  # Refetch item just to verify change occurred
>>> item
{u'id': 'counter', u'n': 21}
Run Code Online (Sandbox Code Playgroud)

这导致与您在Layer1代码中执行的相同的线上请求,如以下调试输出所示.

2012-04-27 04:17:59,170 foo [DEBUG]:StringToSign:
POST
/

host:dynamodb.us-east-1.amazonaws.com
x-amz-date:Fri, 27 Apr 2012 11:17:59 GMT
x-amz-security-    token:<removed> ==
x-amz-target:DynamoDB_20111205.UpdateItem

{"AttributeUpdates": {"n": {"Action": "ADD", "Value": {"N": "20"}}}, "TableName": "counter", "Key": {"HashKeyElement": {"S": "counter"}}}
Run Code Online (Sandbox Code Playgroud)

如果你想避免初始的GetItem调用,你可以这样做:

>>> import boto
>>> c = boto.connect_dynamodb()
>>> t = c.get_table('counter')
>>> item = t.new_item('counter')
>>> item.add_attribute('n', 20)
>>> item.save()
{u'ConsumedCapacityUnits': 1.0}
Run Code Online (Sandbox Code Playgroud)

如果该项目已存在,则会更新该项目,如果该项目尚不存在,则创建该项目.


Jas*_*igh 5

对于那些寻找答案的人我已经找到了.首先重要说明,我目前还没有意识到目前发生了什么,要获得一个我必须执行以下操作的layer1实例:

import boto
AWS_ACCESS_KEY=XXXXX
AWS_SECRET_KEY=YYYYY
dynoConn = boto.connect_dynamodb(AWS_ACCESS_KEY, AWS_SECRET_KEY)
dynoConnLayer1 = boto.dynamodb.layer1.Layer1(AWS_ACCESS_KEY, AWS_SECRET_KEY) 
Run Code Online (Sandbox Code Playgroud)

基本上实例化第2层第一层,然后是第1层.也许我做了一些愚蠢的事情但是在这一点上我很高兴能让它工作......我稍后会对细节进行排序.然后......实际进行原子更新调用:

dynoConnLayer1.update_item("influencer_data", 
                    {"HashKeyElement":{"S":"9f08b4f5-d25a-4950-a948-0381c34aed1c"}},
                    {"direct_influence":
                        {"Action":"ADD","Value":{"N":"20"}}
                    }
                );
Run Code Online (Sandbox Code Playgroud)

请注意,在上面的示例中,Dynamo将ADD 20添加到当前值,并且此操作将是原子意义,意味着在"同一时间"发生的其他操作将在新值建立为+20后正确"调度"发生或执行此操作之前.无论哪种方式,都将实现期望的效果.

确保在layer1连接的实例上执行此操作,因为layer2将抛出错误,因为它需要一组不同的参数类型.

这里的所有都是它的!!!!大家都知道,我用PHP SDK来解决这个问题.安装和设置的时间非常短.当您进行呼叫时,调试数据实际上会显示HTTP请求主体的格式,因此您可以在示例后复制/建模您的layer1参数.这是我用来在PHP中进行原子更新的代码:

<?php 
    // Instantiate the class
    $dynamodb = new AmazonDynamoDB();

    $update_response = $dynamodb->update_item(array(
        'TableName' => 'influencer_data',
            'Key' => array(
                'HashKeyElement' => array(
                    AmazonDynamoDB::TYPE_STRING=> '9f08b4f5-d25a-4950-a948-0381c34aed1c'
                )
            ),
            'AttributeUpdates' => array(
                'direct_influence' => array(
                    'Action' => AmazonDynamoDB::ACTION_ADD,
                    'Value' => array(
                        AmazonDynamoDB::TYPE_NUMBER => '20'
                    )
                )
            )
    ));

    // status code 200 indicates success
    print_r($update_response);

?>
Run Code Online (Sandbox Code Playgroud)

希望这将有助于其他人直到Boto layer2接口赶上...或者有人只是想知道如何在level2中做到这一点:-)