protected function getAll($columns = [], $limit = -1) { $query = ['TableName' => $this->getTable()]; $op = 'Scan'; if ($limit > -1) { $query['limit'] = $limit; } if (!empty($columns)) { $query['AttributesToGet'] = $columns; } // If the $where is not empty, we run getIterator. if (!empty($this->where)) { // Primary key or index key condition exists, then use Query instead of Scan. // However, Query only supports a few conditions. if ($key = $this->conditionsContainIndexKey()) { $condition = array_get($this->where, "{$key}.ComparisonOperator"); if (ComparisonOperator::isValidQueryDynamoDbOperator($condition)) { $op = 'Query'; $query['IndexName'] = $this->dynamoDbIndexKeys[$key]; $query['KeyConditions'] = $this->where; } } $query['ScanFilter'] = $this->where; } $iterator = $this->client->getIterator($op, $query); $results = []; foreach ($iterator as $item) { $item = $this->unmarshalItem($item); $model = new static($item, $this->dynamoDb); $model->setUnfillableAttributes($item); $results[] = $model; } return new Collection($results); }
/** * @depends testIteratesOverScan */ public function testIteratesOverBatchGetItem() { self::log('Running BatchGetItem'); $history = new HistoryPlugin(); $this->client->addSubscriber($history); $iterator = $this->client->getIterator('BatchGetItem', array('RequestItems' => array($this->table => array('Keys' => array(array('HashKeyElement' => array('S' => 'Bar'), 'RangeKeyElement' => array('N' => '10')), array('HashKeyElement' => array('S' => 'Bar'), 'RangeKeyElement' => array('N' => '20')), array('HashKeyElement' => array('S' => 'Bar'), 'RangeKeyElement' => array('N' => '30'))), 'ConsistentRead' => true)))); $items = $iterator->toArray(); $this->client->getEventDispatcher()->removeSubscriber($history); // Ensure that the request was sent using consistent read $this->assertContains('"ConsistentRead":"true"', (string) $history->getLastRequest()->getBody()); $this->assertTrue(count($items) >= 3); $this->assertTrue($iterator->getRequestCount() >= 1); $mustMatch = $this->rangeKeyValues; foreach ($items as $item) { if (false !== ($pos = array_search($item['bar']['N'], $mustMatch))) { unset($mustMatch[$pos]); if (empty($mustMatch)) { break; } } } if (!empty($mustMatch)) { $this->fail('All known items were not found in scan: ' . var_export($mustMatch, true) . ' - found: ' . var_export($items, true)); } }
/** * scan * * @param array $options * * @return array * */ public function scan(array $options = array()) { $options['TableName'] = $this->_table_name; $iterator = self::$_client->getIterator('Scan', $options); $items = array(); foreach ($iterator as $item) { $items[] = $item; } return $this->_formatResults($items); }
/** * Returns all keys that match the pattern given in $pattern. If an asterisk is used it returns all keys that start with the string that precede the asterisk.<br /> * If an asterisk is not used then it returns all keys containing the $pattern. * @param string $pattern * @return array An array containing all matched keys */ public function keys($pattern) { $astPos = mb_strpos($pattern, '*'); if ($astPos !== false && $astPos > 0) { $comparisonOpearator = 'BEGINS_WITH'; $comparisonValue = mb_substr($pattern, 0, $astPos); } else { $comparisonOpearator = 'CONTAINS'; $comparisonValue = $pattern; } $iterator = $this->client->getIterator('Scan', array('TableName' => $this->tableName, 'AttributesToGet' => array(self::SIMPLE_KEY_NAME), 'ReturnConsumedCapacity' => 'TOTAL', 'ScanFilter' => array(self::SIMPLE_KEY_NAME => array('AttributeValueList' => array(array('S' => $comparisonValue)), 'ComparisonOperator' => $comparisonOpearator)))); $keysArray = array(); foreach ($iterator as $item) { $keysArray[] = $item[self::SIMPLE_KEY_NAME]['S']; } return $keysArray; }
/** * Ensures that garbage collection functionality is working correctly */ public function testGarbageCollection() { $currentCount = iterator_count($this->client->getIterator('Scan', array('TableName' => $this->table))); self::log('Put 10 expired items into the sessions table'); $writeBatch = WriteRequestBatch::factory($this->client); for ($i = 1; $i <= 10; $i++) { $writeBatch->add(new PutRequest(Item::fromArray(array('id' => "example_{$i}", 'expires' => time() - 5 * Time::SECONDS)), $this->table)); } $writeBatch->flush(); self::log('Assert that all 10 items made it into the sessions table'); $result = $this->client->getCommand('Scan', array('TableName' => $this->table))->execute(); $this->assertEquals(10 + $currentCount, $result['Count'], 'Not all of the items were inserted.'); self::log('Create a session handler to use with a lower batch size'); $sh = SessionHandler::factory(array('dynamodb_client' => $this->client, 'table_name' => $this->table, 'gc_batch_size' => 3)); self::log('Run the garbage collection'); $sh->garbageCollect(); self::log('Assert that all 10 items were deleted from the sessions table'); $result = $this->client->getCommand('Scan', array('TableName' => $this->table))->execute(); $this->assertEquals(0, $result['Count'], 'Not all of the items were removed.'); }
/** * @depends testIteratesOverScan */ public function testIteratesOverBatchGetItem() { self::log('Running BatchGetItem'); $iterator = $this->client->getIterator('BatchGetItem', array('RequestItems' => array($this->table => array('Keys' => array(array('HashKeyElement' => array('S' => 'Bar'), 'RangeKeyElement' => array('N' => '10')), array('HashKeyElement' => array('S' => 'Bar'), 'RangeKeyElement' => array('N' => '20')), array('HashKeyElement' => array('S' => 'Bar'), 'RangeKeyElement' => array('N' => '30'))))))); $items = $iterator->toArray(); $this->assertTrue(count($items) >= 3); $this->assertTrue($iterator->getRequestCount() >= 1); $mustMatch = $this->rangeKeyValues; foreach ($items as $item) { if (false !== ($pos = array_search($item['bar']['N'], $mustMatch))) { unset($mustMatch[$pos]); if (empty($mustMatch)) { break; } } } if (!empty($mustMatch)) { $this->fail('All known items were not found in scan: ' . var_export($mustMatch, true) . ' - found: ' . var_export($items, true)); } }
/** * Executes a scan or query command. * * @param string $entityClass * @param array|\Cpliakas\DynamoDb\ODM\KeyConditionsInterface $options * @param string $command * @param string $optionKey * * @return \Cpliakas\DynamoDb\ODM\EntityInterface[] * * @throws \InvalidArgumentException * @throws \Aws\DynamoDb\Exception\DynamoDBException */ protected function executeSearchCommand($entityClass, $commandOptions, $command, $optionKey) { if ($commandOptions instanceof ConditionsInterface) { $commandOptions = array($optionKey => $this->formatConditions($entityClass, $commandOptions)) + $commandOptions->getOptions(); } elseif (!is_array($commandOptions)) { throw new \InvalidArgumentException('Expecting command options to be an array or instance of \\Cpliakas\\DynamoDb\\ODM\\KeyConditionsInterface'); } $commandOptions['TableName'] = $this->getEntityTable($entityClass); $commandOptions += array('ConsistentRead' => $this->consistentRead, 'ReturnConsumedCapacity' => $this->returnConsumedCapacity); $command = strtolower($command); $eventNamePrefix = 'dynamo_db.search.'; $this->dispatchSearchRequestEvent($eventNamePrefix . 'pre_' . $command, $entityClass); $iterator = $this->dynamoDb->getIterator($command, $commandOptions); $this->dispatchSearchResponseEvent($eventNamePrefix . 'post_' . $command, $entityClass, $iterator); $entities = array(); foreach ($iterator as $item) { $data = array(); foreach ($item as $attribute => $value) { $data[$attribute] = current($value); } $entities[] = $this->entityFactory($entityClass, $data); } return $entities; }