diff --git a/examples/atlas-search.php b/examples/atlas-search.php
new file mode 100644
index 000000000..53aeb6f6b
--- /dev/null
+++ b/examples/atlas-search.php
@@ -0,0 +1,135 @@
+selectCollection('sample_airbnb', 'listingsAndReviews');
+
+$count = $collection->estimatedDocumentCount();
+if ($count === 0) {
+ echo 'This example requires the sample_airbnb database with the listingsAndReviews 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 "\nThe index already exists. Dropping it.\n";
+ $collection->dropSearchIndex($index->name);
+
+ // Wait for the index to be deleted.
+ wait(function () use ($collection) {
+ foreach ($collection->listSearchIndexes() as $index) {
+ if ($index->name === 'default') {
+ echo '.';
+
+ return false;
+ }
+ }
+
+ echo "\n";
+
+ 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) {
+ foreach ($collection->listSearchIndexes() as $index) {
+ if ($index->name === 'default') {
+ echo '.';
+
+ 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.
+ *
+ * @param Closure():bool $callback
+ */
+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 f1db3e9fa..7776336e9 100644
--- a/psalm-baseline.xml
+++ b/psalm-baseline.xml
@@ -5,6 +5,27 @@
decrypt($document->encryptedField)]]>
+
+
+
+ name]]>
+
+
+
+
+
+ $document
+ $index
+ $index
+ $index
+
+
+ name]]>
+ name]]>
+ name]]>
+ queryable]]>
+
+
self::CURSOR_NOT_FOUND