diff --git a/src/Schema/Builder.php b/src/Schema/Builder.php index ef450745a..998e774aa 100644 --- a/src/Schema/Builder.php +++ b/src/Schema/Builder.php @@ -134,21 +134,34 @@ public function drop($table) $blueprint->drop(); } - /** @inheritdoc */ +/** + * @inheritdoc + * + * Drops the entire database instead of deleting each collection individually. + * + * In MongoDB, dropping the whole database is much faster than dropping collections + * one by one. The database will be automatically recreated when a new connection + * writes to it. + */ public function dropAllTables() { - foreach ($this->getAllCollections() as $collection) { - $this->drop($collection); - } + $this->connection->getDatabase()->drop(); } - /** @param string|null $schema Database name */ + /** @param string|null $schema Database name */ public function getTables($schema = null) { $db = $this->connection->getDatabase($schema); $collections = []; - foreach ($db->listCollectionNames() as $collectionName) { + foreach ($db->listCollections() as $collectionInfo) { + $collectionName = $collectionInfo->getName(); + + // Skip views, which don't support aggregate + if ($collectionInfo->getType() === 'view') { + continue; + } + $stats = $db->selectCollection($collectionName)->aggregate([ ['$collStats' => ['storageStats' => ['scale' => 1]]], ['$project' => ['storageStats.totalSize' => 1]], @@ -165,9 +178,37 @@ public function getTables($schema = null) ]; } - usort($collections, function ($a, $b) { - return $a['name'] <=> $b['name']; - }); + usort($collections, fn ($a, $b) => $a['name'] <=> $b['name']); + + return $collections; + } + + /** @param string|null $schema Database name */ + public function getViews($schema = null) + { + $db = $this->connection->getDatabase($schema); + $collections = []; + + foreach ($db->listCollections() as $collectionInfo) { + $collectionName = $collectionInfo->getName(); + + // Skip normal type collection + if ($collectionInfo->getType() !== 'view') { + continue; + } + + $collections[] = [ + 'name' => $collectionName, + 'schema' => $db->getDatabaseName(), + 'schema_qualified_name' => $db->getDatabaseName() . '.' . $collectionName, + 'size' => null, + 'comment' => null, + 'collation' => null, + 'engine' => null, + ]; + } + + usort($collections, fn ($a, $b) => $a['name'] <=> $b['name']); return $collections; } @@ -195,7 +236,6 @@ public function getTableListing($schema = null, $schemaQualified = false) } $collections = array_merge(...array_values($collections)); - sort($collections); return $collections; diff --git a/tests/SchemaTest.php b/tests/SchemaTest.php index 8e91a2f66..7281ecf7b 100644 --- a/tests/SchemaTest.php +++ b/tests/SchemaTest.php @@ -22,10 +22,11 @@ class SchemaTest extends TestCase { public function tearDown(): void { - $database = $this->getConnection('mongodb')->getMongoDB(); + $database = $this->getConnection('mongodb')->getDatabase(); assert($database instanceof Database); $database->dropCollection('newcollection'); $database->dropCollection('newcollection_two'); + $database->dropCollection('test_view'); parent::tearDown(); } @@ -395,6 +396,7 @@ public function testGetTables() { DB::connection('mongodb')->table('newcollection')->insert(['test' => 'value']); DB::connection('mongodb')->table('newcollection_two')->insert(['test' => 'value']); + DB::connection('mongodb')->getDatabase()->createCollection('test_view', ['viewOn' => 'newcollection']); $dbName = DB::connection('mongodb')->getDatabaseName(); $tables = Schema::getTables(); @@ -407,6 +409,9 @@ public function testGetTables() $this->assertArrayHasKey('schema', $table); $this->assertArrayHasKey('schema_qualified_name', $table); + // Ensure "test_view" is not in the tables list + $this->assertNotEquals('test_view', $table['name'], 'Standard views should not be included in the result of getTables.'); + if ($table['name'] === 'newcollection') { $this->assertEquals(8192, $table['size']); $this->assertEquals($dbName, $table['schema']); @@ -420,6 +425,40 @@ public function testGetTables() } } + public function testGetViews() + { + DB::connection('mongodb')->table('newcollection')->insert(['test' => 'value']); + DB::connection('mongodb')->table('newcollection_two')->insert(['test' => 'value']); + $dbName = DB::connection('mongodb')->getDatabaseName(); + + DB::connection('mongodb')->getDatabase()->createCollection('test_view', ['viewOn' => 'newcollection']); + + $tables = Schema::getViews(); + + $this->assertIsArray($tables); + $this->assertGreaterThanOrEqual(1, count($tables)); + $found = false; + foreach ($tables as $table) { + $this->assertArrayHasKey('name', $table); + $this->assertArrayHasKey('size', $table); + $this->assertArrayHasKey('schema', $table); + $this->assertArrayHasKey('schema_qualified_name', $table); + + // Ensure "normal collections" are not in the views list + $this->assertNotEquals('newcollection', $table['name'], 'Normal collections should not be included in the result of getViews.'); + + if ($table['name'] === 'test_view') { + $this->assertEquals($dbName, $table['schema']); + $this->assertEquals($dbName . '.test_view', $table['schema_qualified_name']); + $found = true; + } + } + + if (! $found) { + $this->fail('Collection "test_view" not found'); + } + } + public function testGetTableListing() { DB::connection('mongodb')->table('newcollection')->insert(['test' => 'value']);