【问题标题】:AWS PHP SDK issue with Dynamodb WriteRequestBatchDynamodb WriteRequestBatch 的 AWS PHP 开发工具包问题
【发布时间】:2014-12-05 06:18:32
【问题描述】:

我正在尝试使用适用于 Dynamodb 的 AWS 开发工具包中的 WriteRequestBatch。下面是我的代码。除 WriteRequestBatch 部分外,一切正常。我不知道为什么,想知道社区是否可以帮助我。我可能做错了什么?我在这里尝试过谷歌搜索和搜索,只发现了其他 8 个可能相关的问题,但不幸的是没有任何帮助。

This 是我的起点。

$ddb_client = DynamoDbClient::factory(array(
    'region' => 'us-east-1',
    'key' => 'my_key',
    'secret' => 'my_secret'
));

$ddb_client->createTable(array(
    'TableName' => 'my_table',
    'AttributeDefinitions' => array(
        array(
            'AttributeName' => 'id',
            'AttributeType' => 'S'
        ),
        array(
            'AttributeName' => 'ns',
            'AttributeType' => 'S'
        )
    ),
    'KeySchema' => array(
        array(
            'AttributeName' => 'id',
            'KeyType'       => 'HASH'
        ),
        array(
            'AttributeName' => 'ns',
            'KeyType'       => 'RANGE'
        )
    ),
    'ProvisionedThroughput' => array(
        'ReadCapacityUnits'  => 10,
        'WriteCapacityUnits' => 10
    )
));

$response = $ddb_client->putItem(array(
    "TableName" => "my_table",
    "Item" => array(
        "id" => array("S" => "exp_id"),
        "ns" => array("S" => "exp_ns"),
        "version" => array("N" => "0"),
    ),
));

$item = $response['Item'];
$item['version']['N'] = '1';

$put_batch = WriteRequestBatch::factory($ddb_client);
$put_request = new PutRequest(
    array(
        "Item" => $item,
        "Expected" => array(
            "version" => array(
                "ComparisonOperator" => "EQ",
                "AttributeValueList" => array(
                    array("N" => "0")
                )
            ),
        ),
    ),
    "my_table"
);
$putBatch->add($put_request);
$putBatch->flush();

这可以代替 WriteRequestBatch。我只需要管理批次来放置自己,而不是使用 WriteRequestBatch 为我做这件事:

$response = $ddb_client->batchWriteItem(array(
    "RequestItems" => array(
        "my_table" => array(
            array(
                "PutRequest" => array(
                    "Item" => $item,
                    "Expected" => array(
                        "version" => array(
                            "ComparisonOperator" => "EQ",
                            "AttributeValueList" => array(
                                array("S" => "0")
                            )
                        ),
                    ),
                )
            )
        )
    )
));

【问题讨论】:

    标签: php amazon-web-services amazon-dynamodb


    【解决方案1】:

    answer by Geek Stocks 不完整,但仍有帮助。您可以处理CreateTable 操作的异步方面的一件事是使用Waiter

    $ddb_client->createTable(array('TableName' => 'my_table', ... ));
    $ddb_client->waitUntil('TableExists', array('TableName' => 'my_table'));
    

    但是,您使用WriteRequestBatch 类的方式也存在问题。创建PutRequest时,必须传入项目,而不是一整套PutItem参数。 WriteRequestBatch 是对 DynamoDB 的 BatchWriteItem operation 的抽象,它不允许 Expected 参数之类的东西。如果你想这样做,那么你需要使用单独的PutItem/UpdateItem/DeleteItem 请求。

    这是您对WriteRequestBatch 用法的修改版本,它是正确的:

    $putBatch = WriteRequestBatch::factory($ddb_client);
    $putBatch->add(new PutRequest($item, 'my_table'));
    // ADD MORE...
    // ...
    // ...
    $putBatch->flush();
    

    Here is another example of using the WriteRequestBatch from the SDK's User Guide.


    编辑:我刚刚测试的另一个完整示例,它显示了 2.7.0 之前和之后的版本之间的差异

    use Aws\DynamoDb\DynamoDbClient;
    use Aws\DynamoDb\Model\BatchRequest\WriteRequestBatch;
    use Aws\DynamoDb\Model\BatchRequest\PutRequest;
    use Aws\DynamoDb\Model\Item;
    
    $client = DynamoDbClient::factory([/* ... */]);
    $batch = WriteRequestBatch::factory($client);
    for ($i = 1; $i <= 55; $i++) {
        // FOR ANY SDK VERSION
        // (NOTE: Does not support new M, L, BOOL, and NULL types)
        $item = Item::fromArray(['id' => $i, 'data' => "foo{$i}"]);
        // FOR SDK >= 2.7
        $item = ['id' => ['N' => $i], 'data' => ['S' => "foo{$i}"]];
    
        $batch->add(new PutRequest($item, 'my-table'));
    }
    $batch->flush();
    

    【讨论】:

    • 实际上 Jeremy,您引用的文档中的代码非常糟糕。尝试直接复制/粘贴,你会明白我的意思。引发“传递给 Aws\DynamoDb\Model\BatchRequest\PutRequest::__construct() 的参数 1 必须是 Aws\DynamoDb\Model\Item 的实例,给定数组...”也许 API 领先于文档?嗯...仍在努力。
    • @Jeremy 不知道你有没有注意到 This 是我开始的地方。,这指向 AWS SDK 链接。
    • 您使用的是什么版本的 SDK?如果它在 2.7 之前,那么我认为您必须使用 Item 类。从 2.7.0 开始,您可以使其与 Item 类或普通数组一起使用。我在答案中添加了一个完整示例,显示了任一版本的用法。
    • @Jeremy 干得好 - 我刚刚测试了你的代码,它运行良好。不确定我从前一个人那里继承了哪个版本的 SDK。我正在寻找一种方式来告诉...
    • echo \Aws\Common\Aws::VERSION; :-)
    【解决方案2】:

    由于您目前没有对代码进行任何“try/catch”错误处理,因此您可能无法获得有关错误的良好信息。

    我在您的代码中放置了 try/catch 块,发现表创建得很好,但是对 putItem 的调用失败,原因如下:找不到请求的资源

    当您创建表时,它不会立即可用。您必须暂停,直到它可用。 This paragraph of the AWS docs 很好地解释了这一点:

    CreateTable 是一个异步操作。收到 CreateTable 请求后,DynamoDB 立即返回一个 TableStatus 为 CREATING 的响应。创建表后,DynamoDB 将 TableStatus 设置为 ACTIVE 。您只能对 ACTIVE 表执行读取和写入操作。您可以使用 DescribeTable API 检查表状态。

    一旦你像它显示的那样添加对 DescribeTable 的调用,你应该会很好。

    【讨论】:

    • 我不知道你是否注意到了,但 除了 WriteRequestBatch 部分之外,一切都正常。在我的实际代码中,我确实在 WriteRequestBatch 部分周围尝试了 catch 块。这里的代码是我根据遇到相同问题的实际代码创建的简化示例。
    • @bagi 很多时候 OP 认为他们的代码的一部分有问题,而实际上他们还没有看到。不,我没有注意到,因为您发布的代码在 WriteRequestBatch 部分之前就中断了。此外,根据文档,您的代码看起来正确。
    • 我应该提到这一点。对此感到抱歉:)
    • 没问题。杰里米的回答很好。很高兴你得到帮助。
    猜你喜欢
    • 2014-12-22
    • 2014-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多