【问题标题】:How can I fetch all items from a DynamoDB table without specifying the primary key?如何在不指定主键的情况下从 DynamoDB 表中获取所有项目?
【发布时间】:2012-05-04 14:38:21
【问题描述】:

我有一个名为 products 的表,主键为 Id。我想选择表中的所有项目。这是我正在使用的代码:

$batch_get_response = $dynamodb->batch_get_item(array(
    'RequestItems' => array(

        'products' => array(
            'Keys' => array(
                array( // Key #1
                    'HashKeyElement'  => array( AmazonDynamoDB::TYPE_NUMBER => '1'),
                    'RangeKeyElement' => array( AmazonDynamoDB::TYPE_NUMBER => $current_time),
                ),
                array( // Key #2
                    'HashKeyElement'  => array( AmazonDynamoDB::TYPE_NUMBER => '2'),
                    'RangeKeyElement' => array( AmazonDynamoDB::TYPE_NUMBER => $current_time),
                ),
            )
        )
    )   
));

是否可以在不指定主键的情况下选择所有项目?我正在使用适用于 PHP 的 AWS 开发工具包。

【问题讨论】:

    标签: php amazon-dynamodb


    【解决方案1】:

    Amazon DynamoDB 为此提供了Scan 操作,该操作通过对表执行全扫描返回一个或多个项目及其属性。请注意以下两个限制:

    • 根据您的表大小,您可能需要使用分页来检索整个结果集:

      注意
      如果扫描的项目总数超过 1MB 限制,则 扫描停止并将结果返回给用户 LastEvaluatedKey 在后续操作中继续扫描。这 结果还包括超出限制的项目数。扫描 可能导致没有符合过滤条件的表数据。

      结果集最终是一致的。

    • 就性能和消耗的容量单位(即价格)而言,扫描操作的成本可能很高,请参阅Query and Scan in Amazon DynamoDB 中的扫描和查询性能部分:

      [...] 此外,随着表的增长,扫描操作会变慢。扫描 操作检查每个项目的请求值,可以用完 在单个操作中为大型表提供的吞吐量。 为了更快的响应时间,请以可以使用的方式设计您的表格 Query、Get 或 BatchGetItem API。或者,设计您的 应用程序以最小化影响的方式使用扫描操作 在您的表的请求率上。有关详细信息,请参阅Provisioned Throughput Guidelines in Amazon DynamoDB[强调我的]

    您可以在Scanning Tables Using the AWS SDK for PHP Low-Level API for Amazon DynamoDB 中找到有关此操作的更多详细信息和一些示例 sn-ps,说明该操作的最简单示例是:

    $dynamodb = new AmazonDynamoDB();
    
    $scan_response = $dynamodb->scan(array(
        'TableName' => 'ProductCatalog' 
    ));
    
    foreach ($scan_response->body->Items as $item)
    {
        echo "<p><strong>Item Number:</strong>"
             . (string) $item->Id->{AmazonDynamoDB::TYPE_NUMBER};
        echo "<br><strong>Item Name: </strong>"
             . (string) $item->Title->{AmazonDynamoDB::TYPE_STRING} ."</p>";
    }
    

    【讨论】:

    • 是否可以在查询中添加条件?
    • 是的,请查看 Request 部分的ScanScanFilter:ComparisonOperator 提供了您可以做什么的摘要。根据您的情况,您可能还想查看Query,这通常出于性能和成本原因(但需要主键)更可取,如Query and Scan in Amazon DynamoDB 中所述。
    • 你能看看我的新问题吗? stackoverflow.com/questions/10477996/…
    • 是否可以获取最后插入的 id(主 ID 的最大值)?
    • @THOmas:不,Primary KeyHash 类型主键Hash 和 Range 类型主键;后者允许项目的相对顺序(参见QueryRangeKeyCondition,但仅此而已。因此(与 NoSQL 解决方案一样),如果你真的需要这个,你需要自己建模(毕竟,你插入了密钥)-您似乎仍然在这里用 SQL 术语想太多;)
    【解决方案2】:

    您好,您可以使用 boto3 下载。在python中

    import boto3
    from boto3.dynamodb.conditions import Key, Attr
    
    dynamodb = boto3.resource('dynamodb')
    table = dynamodb.Table('Table')
    response = table.scan()
    items = response['Items']
    while 'LastEvaluatedKey' in response:
        print(response['LastEvaluatedKey'])
        response = table.scan(ExclusiveStartKey=response['LastEvaluatedKey'])
        items.extend(response['Items'])
    
    

    【讨论】:

    • 到 lib/ 文档的链接会很棒。
    • 扫描不是一项昂贵的操作吗?! @Steffen Opel 解释得很好。
    • @Ronnie 是的,是吗。但是,OP 想要从表中提取所有行。查询将同样昂贵。
    【解决方案3】:

    我认为您正在使用 PHP,但未提及(已编辑)。我通过搜索互联网发现了这个问题,并且由于我的解决方案有效,对于那些使用 nodejs 的人这是一个使用扫描的简单解决方案:

      var dynamoClient = new AWS.DynamoDB.DocumentClient();
      var params = {
        TableName: config.dynamoClient.tableName, // give it your table name 
        Select: "ALL_ATTRIBUTES"
      };
    
      dynamoClient.scan(params, function(err, data) {
        if (err) {
           console.error("Unable to read item. Error JSON:", JSON.stringify(err, null, 2));
        } else {
           console.log("GetItem succeeded:", JSON.stringify(data, null, 2));
        }
      });
    

    我假设同样的代码也可以翻译成 PHP使用不同的 AWS 开发工具包

    【讨论】:

      【解决方案4】:

      我使用以下查询从 dynamodb 获取所有项目。它工作正常。我在 zend 框架中创建这些通用函数并通过项目访问这些函数。

              public function getQuerydata($tablename, $filterKey, $filterValue){
                  return $this->getQuerydataWithOp($tablename, $filterKey, $filterValue, 'EQ');
              }
      
              public function getQuerydataWithOp($tablename, $filterKey, $filterValue, $compOperator){
              $result = $this->getClientdb()->query(array(
                      'TableName'     => $tablename,
                      'IndexName'     => $filterKey,
                      'Select'        => 'ALL_ATTRIBUTES',
                      'KeyConditions' => array(
                          $filterKey => array(
                              'AttributeValueList' => array(
                                  array('S' => $filterValue)
                              ),
                      'ComparisonOperator' => $compOperator
                  )
                  )
              ));
                  return $result['Items'];
              }
      
             //Below i Access these functions and get data.
             $accountsimg = $this->getQuerydataWithPrimary('accounts', 'accountID',$msgdata[0]['accountID']['S']);
      

      【讨论】:

      • 您的数据库中有多少条记录?有 1MB 的限制,看起来这对于较小的数据库非常有用,但如果你有一些大量数据,就无法获取所有内容。
      • 当您获得大于 1 MB 的记录时,您可以使用 amazon db 提供的限制参数。
      • 来自docs.aws.amazon.com/amazondynamodb/latest/developerguide/… :“单个查询或扫描操作最多可以检索 1 MB 的数据。此限制适用于任何过滤器表达式应用于结果之前。”
      • 没有得到 OP 想要的所有项目。
      【解决方案5】:

      通过指定 AWS 服务的区域列出 DynamoDB 表中所有项目的简单代码。

      import boto3
      
      dynamodb = boto3.resource('dynamodb', region_name='ap-south-1')
      table = dynamodb.Table('puppy_store')
      response = table.scan()
      items = response['Items']
      
      # Prints All the Items at once
      print(items)
      
      # Prints Items line by line
      for i, j in enumerate(items):
          print(f"Num: {i} --> {j}")
      

      【讨论】:

      • 我错过了 item 中多余的 's'。
      【解决方案6】:

      我没有在以下代码上指定 pk:

      client = boto3.client('dynamodb')
      table = 'table_name'
      response = client.scan(
          TableName=table,
          AttributesToGet=['second_field_in_order', 'first_field_in_order']
      )
      

      【讨论】:

        【解决方案7】:

        此 C# 代码是使用 BatchGet 或 CreateBatchGet 从 dynamodb 表中获取所有项目

                string tablename = "AnyTableName"; //table whose data you want to fetch
        
                var BatchRead = ABCContext.Context.CreateBatchGet<ABCTable>(  
        
                    new DynamoDBOperationConfig
                    {
                        OverrideTableName = tablename; 
                    });
        
                foreach(string Id in IdList) // in case you are taking string from input
                {
                    Guid objGuid = Guid.Parse(Id); //parsing string to guid
                    BatchRead.AddKey(objGuid);
                }
        
                await BatchRead.ExecuteAsync();
                var result = BatchRead.Results;
        

        // ABCTable是表格模态,用于在dynamodb中创建你要获取的数据

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-02-11
          • 2020-04-17
          • 2019-08-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多