|
6 | 6 |
|
7 | 7 | use Closure;
|
8 | 8 | use MongoDB\Collection;
|
| 9 | +use MongoDB\Database; |
9 | 10 | use MongoDB\Driver\Exception\ServerException;
|
10 | 11 | use MongoDB\Laravel\Connection;
|
11 | 12 | use MongoDB\Model\CollectionInfo;
|
|
14 | 15 | use function array_column;
|
15 | 16 | use function array_fill_keys;
|
16 | 17 | use function array_filter;
|
| 18 | +use function array_key_exists; |
17 | 19 | use function array_keys;
|
18 | 20 | use function array_map;
|
19 | 21 | use function array_merge;
|
|
25 | 27 | use function implode;
|
26 | 28 | use function in_array;
|
27 | 29 | use function is_array;
|
| 30 | +use function is_bool; |
28 | 31 | use function is_string;
|
29 | 32 | use function iterator_to_array;
|
30 | 33 | use function sort;
|
@@ -156,66 +159,13 @@ public function dropAllTables()
|
156 | 159 | /** @param string|null $schema Database name */
|
157 | 160 | public function getTables($schema = null)
|
158 | 161 | {
|
159 |
| - $db = $this->connection->getDatabase($schema); |
160 |
| - $collections = []; |
161 |
| - |
162 |
| - foreach ($db->listCollections() as $collectionInfo) { |
163 |
| - $collectionName = $collectionInfo->getName(); |
164 |
| - |
165 |
| - // Skip views, which don't support aggregate |
166 |
| - if ($collectionInfo->getType() === 'view') { |
167 |
| - continue; |
168 |
| - } |
169 |
| - |
170 |
| - $stats = $db->selectCollection($collectionName)->aggregate([ |
171 |
| - ['$collStats' => ['storageStats' => ['scale' => 1]]], |
172 |
| - ['$project' => ['storageStats.totalSize' => 1]], |
173 |
| - ])->toArray(); |
174 |
| - |
175 |
| - $collections[] = [ |
176 |
| - 'name' => $collectionName, |
177 |
| - 'schema' => $db->getDatabaseName(), |
178 |
| - 'schema_qualified_name' => $db->getDatabaseName() . '.' . $collectionName, |
179 |
| - 'size' => $stats[0]?->storageStats?->totalSize ?? null, |
180 |
| - 'comment' => null, |
181 |
| - 'collation' => null, |
182 |
| - 'engine' => null, |
183 |
| - ]; |
184 |
| - } |
185 |
| - |
186 |
| - usort($collections, fn ($a, $b) => $a['name'] <=> $b['name']); |
187 |
| - |
188 |
| - return $collections; |
| 162 | + return $this->getCollectionRows('collection', $schema); |
189 | 163 | }
|
190 | 164 |
|
191 | 165 | /** @param string|null $schema Database name */
|
192 | 166 | public function getViews($schema = null)
|
193 | 167 | {
|
194 |
| - $db = $this->connection->getDatabase($schema); |
195 |
| - $collections = []; |
196 |
| - |
197 |
| - foreach ($db->listCollections() as $collectionInfo) { |
198 |
| - $collectionName = $collectionInfo->getName(); |
199 |
| - |
200 |
| - // Skip normal type collection |
201 |
| - if ($collectionInfo->getType() !== 'view') { |
202 |
| - continue; |
203 |
| - } |
204 |
| - |
205 |
| - $collections[] = [ |
206 |
| - 'name' => $collectionName, |
207 |
| - 'schema' => $db->getDatabaseName(), |
208 |
| - 'schema_qualified_name' => $db->getDatabaseName() . '.' . $collectionName, |
209 |
| - 'size' => null, |
210 |
| - 'comment' => null, |
211 |
| - 'collation' => null, |
212 |
| - 'engine' => null, |
213 |
| - ]; |
214 |
| - } |
215 |
| - |
216 |
| - usort($collections, fn ($a, $b) => $a['name'] <=> $b['name']); |
217 |
| - |
218 |
| - return $collections; |
| 168 | + return $this->getCollectionRows('view', $schema); |
219 | 169 | }
|
220 | 170 |
|
221 | 171 | /**
|
@@ -254,7 +204,7 @@ public function getColumns($table)
|
254 | 204 | [$db, $table] = explode('.', $table, 2);
|
255 | 205 | }
|
256 | 206 |
|
257 |
| - $stats = $this->connection->getDatabase($db)->selectCollection($table)->aggregate([ |
| 207 | + $stats = $this->connection->getDatabase($db)->getCollection($table)->aggregate([ |
258 | 208 | // Sample 1,000 documents to get a representative sample of the collection
|
259 | 209 | ['$sample' => ['size' => 1_000]],
|
260 | 210 | // Convert each document to an array of fields
|
@@ -389,7 +339,7 @@ public function getCollection($name)
|
389 | 339 | }
|
390 | 340 |
|
391 | 341 | /**
|
392 |
| - * Get all of the collections names for the database. |
| 342 | + * Get all the collections names for the database. |
393 | 343 | *
|
394 | 344 | * @deprecated
|
395 | 345 | *
|
@@ -418,4 +368,68 @@ public static function isAtlasSearchNotSupportedException(ServerException $e): b
|
418 | 368 | 31082, // MongoDB 8: Using Atlas Search Database Commands and the $listSearchIndexes aggregation stage requires additional configuration.
|
419 | 369 | ], true);
|
420 | 370 | }
|
| 371 | + |
| 372 | + /** @param string|null $schema Database name */ |
| 373 | + private function getCollectionRows(string $collectionType, $schema = null) |
| 374 | + { |
| 375 | + $db = $this->connection->getDatabase($schema); |
| 376 | + $collections = []; |
| 377 | + |
| 378 | + foreach ($db->listCollections() as $collectionInfo) { |
| 379 | + $collectionName = $collectionInfo->getName(); |
| 380 | + |
| 381 | + if ($collectionInfo->getType() !== $collectionType) { |
| 382 | + continue; |
| 383 | + } |
| 384 | + |
| 385 | + $options = $collectionInfo->getOptions(); |
| 386 | + $collation = $options['collation'] ?? []; |
| 387 | + |
| 388 | + // Aggregation is not supported on views |
| 389 | + $stats = $collectionType !== 'view' ? $db->selectCollection($collectionName)->aggregate([ |
| 390 | + ['$collStats' => ['storageStats' => ['scale' => 1]]], |
| 391 | + ['$project' => ['storageStats.totalSize' => 1]], |
| 392 | + ])->toArray() : null; |
| 393 | + |
| 394 | + $collections[] = [ |
| 395 | + 'name' => $collectionName, |
| 396 | + 'schema' => $db->getDatabaseName(), |
| 397 | + 'schema_qualified_name' => $db->getDatabaseName() . '.' . $collectionName, |
| 398 | + 'size' => $stats[0]?->storageStats?->totalSize ?? null, |
| 399 | + 'comment' => null, |
| 400 | + 'collation' => $this->collationToString($collation), |
| 401 | + 'engine' => null, |
| 402 | + ]; |
| 403 | + } |
| 404 | + |
| 405 | + usort($collections, fn ($a, $b) => $a['name'] <=> $b['name']); |
| 406 | + |
| 407 | + return $collections; |
| 408 | + } |
| 409 | + |
| 410 | + private function collationToString(array $collation): string |
| 411 | + { |
| 412 | + $map = [ |
| 413 | + 'locale' => 'l', |
| 414 | + 'strength' => 's', |
| 415 | + 'caseLevel' => 'cl', |
| 416 | + 'caseFirst' => 'cf', |
| 417 | + 'numericOrdering' => 'no', |
| 418 | + 'alternate' => 'a', |
| 419 | + 'maxVariable' => 'mv', |
| 420 | + 'normalization' => 'n', |
| 421 | + 'backwards' => 'b', |
| 422 | + ]; |
| 423 | + |
| 424 | + $parts = []; |
| 425 | + foreach ($collation as $key => $value) { |
| 426 | + if (array_key_exists($key, $map)) { |
| 427 | + $shortKey = $map[$key]; |
| 428 | + $shortValue = is_bool($value) ? ($value ? '1' : '0') : $value; |
| 429 | + $parts[] = $shortKey . '=' . $shortValue; |
| 430 | + } |
| 431 | + } |
| 432 | + |
| 433 | + return implode(';', $parts); |
| 434 | + } |
421 | 435 | }
|
0 commit comments