From 758984085c6f516df119b98eb2613e92516e1a18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Tamarelle?= Date: Wed, 13 Sep 2023 17:15:45 +0200 Subject: [PATCH] Add Atlas Search example (#1147) * Create Atlas Search example * Add fixtures to run atlas-search example in CI --- examples/atlas-search.php | 133 ++++++++++++++++++++++++++++++++++++++ psalm-baseline.xml | 24 +++++++ tests/ExamplesTest.php | 54 ++++++++++++++++ 3 files changed, 211 insertions(+) create mode 100644 examples/atlas-search.php diff --git a/examples/atlas-search.php b/examples/atlas-search.php new file mode 100644 index 000000000..938751256 --- /dev/null +++ b/examples/atlas-search.php @@ -0,0 +1,133 @@ +selectCollection($databaseName, $collectionName); + +$count = $collection->estimatedDocumentCount(); +if ($count === 0) { + echo 'This example requires the "', $databaseName, '" database with the "', $collectionName, '" collection.', "\n"; + echo 'Load the sample dataset in your MongoDB Atlas cluster before running this example:', "\n"; + echo ' https://www.mongodb.com/docs/atlas/sample-data/', "\n"; + exit(1); +} + +// Delete the index if it already exists +$indexes = iterator_to_array($collection->listSearchIndexes()); +foreach ($indexes as $index) { + if ($index->name === 'default') { + echo "The index already exists. Dropping it.\n"; + $collection->dropSearchIndex($index->name); + + // Wait for the index to be deleted. + wait(function () use ($collection) { + echo '.'; + foreach ($collection->listSearchIndexes() as $index) { + if ($index->name === 'default') { + return false; + } + } + + return true; + }); + } +} + +// Create the search index +echo "\nCreating the index.\n"; +$collection->createSearchIndex( + /* The index definition requires a mapping + * See: https://www.mongodb.com/docs/atlas/atlas-search/define-field-mappings/ */ + ['mappings' => ['dynamic' => true]], + // "default" is the default index name, this config can be omitted. + ['name' => 'default'], +); + +// Wait for the index to be ready. +wait(function () use ($collection) { + echo '.'; + foreach ($collection->listSearchIndexes() as $index) { + if ($index->name === 'default') { + return $index->queryable; + } + } + + return false; +}); + +// Perform a text search +echo "\n", 'Performing a text search...', "\n"; +$results = $collection->aggregate([ + [ + '$search' => [ + 'index' => 'default', + 'text' => [ + 'query' => 'view beach ocean', + 'path' => ['name'], + ], + ], + ], + ['$project' => ['name' => 1, 'description' => 1]], + ['$limit' => 10], +])->toArray(); + +foreach ($results as $document) { + echo ' - ', $document['name'], "\n"; +} + +echo "\n", 'Enjoy MongoDB Atlas Search!', "\n\n"; + +/** + * This function waits until the callback returns true or the timeout is reached. + */ +function wait(Closure $callback): void +{ + $timeout = hrtime()[0] + WAIT_TIMEOUT_SEC; + while (hrtime()[0] < $timeout) { + if ($callback()) { + return; + } + + sleep(5); + } + + throw new RuntimeException('Time out'); +} diff --git a/psalm-baseline.xml b/psalm-baseline.xml index db2c99aed..fcc5cc66f 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -5,6 +5,30 @@ decrypt($document->encryptedField)]]> + + + + name]]> + + + + + + $document + $index + $index + $index + + + name]]> + name]]> + name]]> + queryable]]> + + + $uri + + markTestSkipped('Atlas Search examples are only supported on MongoDB Atlas'); + } + + $this->skipIfServerVersion('<', '7.0', 'Atlas Search examples require MongoDB 7.0 or later'); + + // Generate random collection name to avoid conflicts with consecutive runs as the index creation is asynchronous + $collectionName = sprintf('%s.%s', $this->getCollectionName(), bin2hex(random_bytes(5))); + $databaseName = $this->getDatabaseName(); + $collection = $this->createCollection($databaseName, $collectionName); + $collection->insertMany([ + ['name' => 'Ribeira Charming Duplex'], + ['name' => 'Ocean View Bondi Beach'], + ['name' => 'Luxury ocean view Beach Villa 622'], + ['name' => 'Ocean & Beach View Condo WBR H204'], + ['name' => 'Bondi Beach Spacious Studio With Ocean View'], + ['name' => 'New York City - Upper West Side Apt'], + ]); + putenv(sprintf('MONGODB_DATABASE=%s', $databaseName)); + putenv(sprintf('MONGODB_COLLECTION=%s', $collectionName)); + + $expectedOutput = <<<'OUTPUT' + +Creating the index. +%s +Performing a text search... + - Ocean View Bondi Beach + - Luxury ocean view Beach Villa 622 + - Ocean & Beach View Condo WBR H204 + - Bondi Beach Spacious Studio With Ocean View + +Enjoy MongoDB Atlas Search! + + +OUTPUT; + + $this->assertExampleOutput(__DIR__ . '/../examples/atlas-search.php', $expectedOutput); + } + public function testChangeStream(): void { $this->skipIfChangeStreamIsNotSupported();