Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PHPLIB-1143: Add search index operations to Collection class #1097

Merged
merged 5 commits into from
Aug 31, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@
<code>($value is NativeType ? BSONType : $value)</code>
</MixedInferredReturnType>
</file>
<file src="src/Collection.php">
<MixedArgumentTypeCoercion>
<code>$options</code>
</MixedArgumentTypeCoercion>
</file>
<file src="src/Command/ListCollections.php">
<MixedAssignment>
<code>$cmd[$option]</code>
Expand Down Expand Up @@ -317,6 +322,14 @@
<code>isInTransaction</code>
</MixedMethodCall>
</file>
<file src="src/Operation/CreateSearchIndexes.php">
<MixedArgumentTypeCoercion>
<code>$index</code>
</MixedArgumentTypeCoercion>
<MixedAssignment>
<code><![CDATA[$cmd['comment']]]></code>
</MixedAssignment>
</file>
<file src="src/Operation/DatabaseCommand.php">
<MixedArgument>
<code><![CDATA[$this->options['typeMap']]]></code>
Expand Down Expand Up @@ -397,6 +410,11 @@
<code>isInTransaction</code>
</MixedMethodCall>
</file>
<file src="src/Operation/DropSearchIndex.php">
<MixedAssignment>
<code><![CDATA[$cmd['comment']]]></code>
</MixedAssignment>
</file>
<file src="src/Operation/Explain.php">
<MixedArgument>
<code><![CDATA[$this->options['typeMap']]]></code>
Expand Down Expand Up @@ -576,6 +594,11 @@
<code>isInTransaction</code>
</MixedMethodCall>
</file>
<file src="src/Operation/UpdateSearchIndex.php">
<MixedAssignment>
<code><![CDATA[$cmd['comment']]]></code>
</MixedAssignment>
</file>
<file src="src/Operation/Watch.php">
<MixedArgument>
<code><![CDATA[$reply->cursor->firstBatch]]></code>
Expand Down
118 changes: 118 additions & 0 deletions src/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

namespace MongoDB;

use Countable;
use Iterator;
use MongoDB\BSON\JavascriptInterface;
use MongoDB\Codec\DocumentCodec;
Expand All @@ -38,12 +39,14 @@
use MongoDB\Operation\Count;
use MongoDB\Operation\CountDocuments;
use MongoDB\Operation\CreateIndexes;
use MongoDB\Operation\CreateSearchIndexes;
use MongoDB\Operation\DeleteMany;
use MongoDB\Operation\DeleteOne;
use MongoDB\Operation\Distinct;
use MongoDB\Operation\DropCollection;
use MongoDB\Operation\DropEncryptedCollection;
use MongoDB\Operation\DropIndexes;
use MongoDB\Operation\DropSearchIndex;
use MongoDB\Operation\EstimatedDocumentCount;
use MongoDB\Operation\Explain;
use MongoDB\Operation\Explainable;
Expand All @@ -55,11 +58,13 @@
use MongoDB\Operation\InsertMany;
use MongoDB\Operation\InsertOne;
use MongoDB\Operation\ListIndexes;
use MongoDB\Operation\ListSearchIndexes;
use MongoDB\Operation\MapReduce;
use MongoDB\Operation\RenameCollection;
use MongoDB\Operation\ReplaceOne;
use MongoDB\Operation\UpdateMany;
use MongoDB\Operation\UpdateOne;
use MongoDB\Operation\UpdateSearchIndex;
use MongoDB\Operation\Watch;

use function array_diff_key;
Expand Down Expand Up @@ -360,6 +365,64 @@ public function createIndexes(array $indexes, array $options = [])
return $operation->execute(select_server($this->manager, $options));
}

/**
* Create an Atlas Search index for the collection.
* Only available when used against a 7.0+ Atlas cluster.
GromNaN marked this conversation as resolved.
Show resolved Hide resolved
*
* @see https://www.mongodb.com/docs/manual/reference/command/createSearchIndexes/
jmikola marked this conversation as resolved.
Show resolved Hide resolved
* @see https://mongodb.com/docs/manual/reference/method/db.collection.createSearchIndex/
* @param array|object $definition Atlas Search index mapping definition
* @param array{name?: string, comment?: mixed} $options Command options
* @return string The name of the created search index
* @throws UnsupportedException if options are not supported by the selected server
* @throws InvalidArgumentException for parameter/option parsing errors
* @throws DriverRuntimeException for other driver errors (e.g. connection errors)
*/
public function createSearchIndex($definition, array $options = []): string
{
$index = ['definition' => $definition];
if (isset($options['name'])) {
$index['name'] = $options['name'];
unset($options['name']);
}

$names = $this->createSearchIndexes([$index], $options);

return current($names);
jmikola marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* Create one or more Atlas Search indexes for the collection.
* Only available when used against a 7.0+ Atlas cluster.
*
* Each element in the $indexes array must have "definition" document and they may have a "name" string.
* The name can be omitted for a single index, in which case a name will be the default.
* For example:
*
* $indexes = [
* // Create a search index with the default name, on
* ['definition' => ['mappings' => ['dynamic' => false, 'fields' => ['title' => ['type' => 'string']]]]],
* // Create a named search index on all fields
* ['name' => 'search_all', 'definition' => ['mappings' => ['dynamic' => true]]],
* ];
*
* @see https://www.mongodb.com/docs/manual/reference/command/createSearchIndexes/
* @see https://mongodb.com/docs/manual/reference/method/db.collection.createSearchIndex/
* @param list<array{name?: string, definition: array|object}> $indexes List of search index specifications
* @param array{comment?: string} $options Command options
* @return string[] The names of the created search indexes
* @throws UnsupportedException if options are not supported by the selected server
* @throws InvalidArgumentException for parameter/option parsing errors
* @throws DriverRuntimeException for other driver errors (e.g. connection errors)
*/
public function createSearchIndexes(array $indexes, array $options = []): array
GromNaN marked this conversation as resolved.
Show resolved Hide resolved
{
$operation = new CreateSearchIndexes($this->databaseName, $this->collectionName, $indexes, $options);
$server = select_server($this->manager, $options);

return $operation->execute($server);
}

/**
* Deletes all documents matching the filter.
*
Expand Down Expand Up @@ -501,6 +564,24 @@ public function dropIndexes(array $options = [])
return $operation->execute(select_server($this->manager, $options));
}

/**
* Drop a single Atlas Search index in the collection.
* Only available when used against a 7.0+ Atlas cluster.
*
* @param string $name Search index name
* @param array{comment?: mixed} $options Additional options
* @throws UnsupportedException if options are not supported by the selected server
* @throws InvalidArgumentException for parameter/option parsing errors
* @throws DriverRuntimeException for other driver errors (e.g. connection errors)
*/
public function dropSearchIndex(string $name, array $options = []): void
{
$operation = new DropSearchIndex($this->databaseName, $this->collectionName, $name);
$server = select_server($this->manager, $options);

$operation->execute($server);
}

/**
* Gets an estimated number of documents in the collection using the collection metadata.
*
Expand Down Expand Up @@ -812,6 +893,24 @@ public function listIndexes(array $options = [])
return $operation->execute(select_server($this->manager, $options));
}

/**
* Returns information for all Atlas Search indexes for the collection.
* Only available when used against a 7.0+ Atlas cluster.
jmikola marked this conversation as resolved.
Show resolved Hide resolved
*
* @param array{name?: string} $options Command options
* @return Countable&Iterator
* @throws InvalidArgumentException for parameter/option parsing errors
* @throws DriverRuntimeException for other driver errors (e.g. connection errors)
* @see ListSearchIndexes::__construct() for supported options
*/
public function listSearchIndexes(array $options = []): Iterator
{
$operation = new ListSearchIndexes($this->databaseName, $this->collectionName, $options);
$server = select_server($this->manager, $options);

return $operation->execute($server);
}

/**
* Executes a map-reduce aggregation on the collection.
*
Expand Down Expand Up @@ -946,6 +1045,25 @@ public function updateOne($filter, $update, array $options = [])
return $operation->execute(select_server($this->manager, $options));
}

/**
* Update a single Atlas Search index in the collection.
* Only available when used against a 7.0+ Atlas cluster.
*
* @param string $name Search index name
* @param array|object $definition Atlas Search index definition
* @param array{comment?: mixed} $options Command options
* @throws UnsupportedException if options are not supported by the selected server
* @throws InvalidArgumentException for parameter parsing errors
* @throws DriverRuntimeException for other driver errors (e.g. connection errors)
*/
public function updateSearchIndex(string $name, $definition, array $options = []): void
{
$operation = new UpdateSearchIndex($this->databaseName, $this->collectionName, $name, $definition, $options);
$server = select_server($this->manager, $options);

$operation->execute($server);
}

/**
* Create a change stream for watching changes to the collection.
*
Expand Down
4 changes: 2 additions & 2 deletions src/Model/IndexInput.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@ public function __toString(): string
* @see \MongoDB\Collection::createIndexes()
* @see https://php.net/mongodb-bson-serializable.bsonserialize
*/
public function bsonSerialize(): array
public function bsonSerialize(): object
{
return $this->index;
return (object) $this->index;
}

/**
Expand Down
73 changes: 73 additions & 0 deletions src/Model/SearchIndexInput.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php
/*
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

namespace MongoDB\Model;

use MongoDB\BSON\Serializable;
use MongoDB\Exception\InvalidArgumentException;

use function is_string;
use function MongoDB\is_document;

/**
* Search index input model class.
*
* This class is used to validate user input for search index creation.
*
* @internal
* @see \MongoDB\Collection::createSearchIndexes()
* @see https://github.com/mongodb/specifications/blob/master/source/index-management/index-management.rst#search-indexes
* @see https://mongodb.com/docs/manual/reference/method/db.collection.createSearchIndex/
*/
class SearchIndexInput implements Serializable
{
/** @var array */
private array $index;

/**
* @param array{name?: string, definition: array|object} $index Search index specification
* @throws InvalidArgumentException
*/
public function __construct(array $index)
{
if (! isset($index['definition'])) {
throw new InvalidArgumentException('Required "definition" document is missing from search index specification');
}

if (! is_document($index['definition'])) {
throw InvalidArgumentException::expectedDocumentType('"definition" option', $index['definition']);
}
jmikola marked this conversation as resolved.
Show resolved Hide resolved

// Name is optional, but must be a non-empty string if provided
if (isset($index['name']) && ! is_string($index['name'])) {
throw InvalidArgumentException::invalidType('"name" option', $index['name'], 'string');
}

$this->index = $index;
}

/**
* Serialize the search index information to BSON for search index creation.
*
* @see \MongoDB\Collection::createSearchIndexes()
* @see https://php.net/mongodb-bson-serializable.bsonserialize
*/
public function bsonSerialize(): object
{
return (object) $this->index;
}
}
Loading