vendor/mongodb/mongodb/src/Collection.php line 654

Open in your IDE?
  1. <?php
  2. /*
  3.  * Copyright 2015-present MongoDB, Inc.
  4.  *
  5.  * Licensed under the Apache License, Version 2.0 (the "License");
  6.  * you may not use this file except in compliance with the License.
  7.  * You may obtain a copy of the License at
  8.  *
  9.  *   https://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. namespace MongoDB;
  18. use MongoDB\BSON\JavascriptInterface;
  19. use MongoDB\Driver\Cursor;
  20. use MongoDB\Driver\Exception\RuntimeException as DriverRuntimeException;
  21. use MongoDB\Driver\Manager;
  22. use MongoDB\Driver\ReadConcern;
  23. use MongoDB\Driver\ReadPreference;
  24. use MongoDB\Driver\WriteConcern;
  25. use MongoDB\Exception\InvalidArgumentException;
  26. use MongoDB\Exception\UnexpectedValueException;
  27. use MongoDB\Exception\UnsupportedException;
  28. use MongoDB\Model\BSONArray;
  29. use MongoDB\Model\BSONDocument;
  30. use MongoDB\Model\IndexInfo;
  31. use MongoDB\Model\IndexInfoIterator;
  32. use MongoDB\Operation\Aggregate;
  33. use MongoDB\Operation\BulkWrite;
  34. use MongoDB\Operation\Count;
  35. use MongoDB\Operation\CountDocuments;
  36. use MongoDB\Operation\CreateIndexes;
  37. use MongoDB\Operation\DeleteMany;
  38. use MongoDB\Operation\DeleteOne;
  39. use MongoDB\Operation\Distinct;
  40. use MongoDB\Operation\DropCollection;
  41. use MongoDB\Operation\DropIndexes;
  42. use MongoDB\Operation\EstimatedDocumentCount;
  43. use MongoDB\Operation\Explain;
  44. use MongoDB\Operation\Explainable;
  45. use MongoDB\Operation\Find;
  46. use MongoDB\Operation\FindOne;
  47. use MongoDB\Operation\FindOneAndDelete;
  48. use MongoDB\Operation\FindOneAndReplace;
  49. use MongoDB\Operation\FindOneAndUpdate;
  50. use MongoDB\Operation\InsertMany;
  51. use MongoDB\Operation\InsertOne;
  52. use MongoDB\Operation\ListIndexes;
  53. use MongoDB\Operation\MapReduce;
  54. use MongoDB\Operation\RenameCollection;
  55. use MongoDB\Operation\ReplaceOne;
  56. use MongoDB\Operation\UpdateMany;
  57. use MongoDB\Operation\UpdateOne;
  58. use MongoDB\Operation\Watch;
  59. use Traversable;
  60. use function array_diff_key;
  61. use function array_intersect_key;
  62. use function current;
  63. use function is_array;
  64. use function strlen;
  65. class Collection
  66. {
  67.     /** @var array */
  68.     private static $defaultTypeMap = [
  69.         'array' => BSONArray::class,
  70.         'document' => BSONDocument::class,
  71.         'root' => BSONDocument::class,
  72.     ];
  73.     /** @var integer */
  74.     private static $wireVersionForReadConcernWithWriteStage 8;
  75.     /** @var string */
  76.     private $collectionName;
  77.     /** @var string */
  78.     private $databaseName;
  79.     /** @var Manager */
  80.     private $manager;
  81.     /** @var ReadConcern */
  82.     private $readConcern;
  83.     /** @var ReadPreference */
  84.     private $readPreference;
  85.     /** @var array */
  86.     private $typeMap;
  87.     /** @var WriteConcern */
  88.     private $writeConcern;
  89.     /**
  90.      * Constructs new Collection instance.
  91.      *
  92.      * This class provides methods for collection-specific operations, such as
  93.      * CRUD (i.e. create, read, update, and delete) and index management.
  94.      *
  95.      * Supported options:
  96.      *
  97.      *  * readConcern (MongoDB\Driver\ReadConcern): The default read concern to
  98.      *    use for collection operations. Defaults to the Manager's read concern.
  99.      *
  100.      *  * readPreference (MongoDB\Driver\ReadPreference): The default read
  101.      *    preference to use for collection operations. Defaults to the Manager's
  102.      *    read preference.
  103.      *
  104.      *  * typeMap (array): Default type map for cursors and BSON documents.
  105.      *
  106.      *  * writeConcern (MongoDB\Driver\WriteConcern): The default write concern
  107.      *    to use for collection operations. Defaults to the Manager's write
  108.      *    concern.
  109.      *
  110.      * @param Manager $manager        Manager instance from the driver
  111.      * @param string  $databaseName   Database name
  112.      * @param string  $collectionName Collection name
  113.      * @param array   $options        Collection options
  114.      * @throws InvalidArgumentException for parameter/option parsing errors
  115.      */
  116.     public function __construct(Manager $managerstring $databaseNamestring $collectionName, array $options = [])
  117.     {
  118.         if (strlen($databaseName) < 1) {
  119.             throw new InvalidArgumentException('$databaseName is invalid: ' $databaseName);
  120.         }
  121.         if (strlen($collectionName) < 1) {
  122.             throw new InvalidArgumentException('$collectionName is invalid: ' $collectionName);
  123.         }
  124.         if (isset($options['readConcern']) && ! $options['readConcern'] instanceof ReadConcern) {
  125.             throw InvalidArgumentException::invalidType('"readConcern" option'$options['readConcern'], ReadConcern::class);
  126.         }
  127.         if (isset($options['readPreference']) && ! $options['readPreference'] instanceof ReadPreference) {
  128.             throw InvalidArgumentException::invalidType('"readPreference" option'$options['readPreference'], ReadPreference::class);
  129.         }
  130.         if (isset($options['typeMap']) && ! is_array($options['typeMap'])) {
  131.             throw InvalidArgumentException::invalidType('"typeMap" option'$options['typeMap'], 'array');
  132.         }
  133.         if (isset($options['writeConcern']) && ! $options['writeConcern'] instanceof WriteConcern) {
  134.             throw InvalidArgumentException::invalidType('"writeConcern" option'$options['writeConcern'], WriteConcern::class);
  135.         }
  136.         $this->manager $manager;
  137.         $this->databaseName $databaseName;
  138.         $this->collectionName $collectionName;
  139.         $this->readConcern $options['readConcern'] ?? $this->manager->getReadConcern();
  140.         $this->readPreference $options['readPreference'] ?? $this->manager->getReadPreference();
  141.         $this->typeMap $options['typeMap'] ?? self::$defaultTypeMap;
  142.         $this->writeConcern $options['writeConcern'] ?? $this->manager->getWriteConcern();
  143.     }
  144.     /**
  145.      * Return internal properties for debugging purposes.
  146.      *
  147.      * @see https://php.net/manual/en/language.oop5.magic.php#language.oop5.magic.debuginfo
  148.      * @return array
  149.      */
  150.     public function __debugInfo()
  151.     {
  152.         return [
  153.             'collectionName' => $this->collectionName,
  154.             'databaseName' => $this->databaseName,
  155.             'manager' => $this->manager,
  156.             'readConcern' => $this->readConcern,
  157.             'readPreference' => $this->readPreference,
  158.             'typeMap' => $this->typeMap,
  159.             'writeConcern' => $this->writeConcern,
  160.         ];
  161.     }
  162.     /**
  163.      * Return the collection namespace (e.g. "db.collection").
  164.      *
  165.      * @see https://mongodb.com/docs/manual/core/databases-and-collections/
  166.      * @return string
  167.      */
  168.     public function __toString()
  169.     {
  170.         return $this->databaseName '.' $this->collectionName;
  171.     }
  172.     /**
  173.      * Executes an aggregation framework pipeline on the collection.
  174.      *
  175.      * Note: this method's return value depends on the MongoDB server version
  176.      * and the "useCursor" option. If "useCursor" is true, a Cursor will be
  177.      * returned; otherwise, an ArrayIterator is returned, which wraps the
  178.      * "result" array from the command response document.
  179.      *
  180.      * @see Aggregate::__construct() for supported options
  181.      * @param array $pipeline List of pipeline operations
  182.      * @param array $options  Command options
  183.      * @return Traversable
  184.      * @throws UnexpectedValueException if the command response was malformed
  185.      * @throws UnsupportedException if options are not supported by the selected server
  186.      * @throws InvalidArgumentException for parameter/option parsing errors
  187.      * @throws DriverRuntimeException for other driver errors (e.g. connection errors)
  188.      */
  189.     public function aggregate(array $pipeline, array $options = [])
  190.     {
  191.         $hasWriteStage is_last_pipeline_operator_write($pipeline);
  192.         if (! isset($options['readPreference']) && ! is_in_transaction($options)) {
  193.             $options['readPreference'] = $this->readPreference;
  194.         }
  195.         $server $hasWriteStage
  196.             select_server_for_aggregate_write_stage($this->manager$options)
  197.             : select_server($this->manager$options);
  198.         /* MongoDB 4.2 and later supports a read concern when an $out stage is
  199.          * being used, but earlier versions do not.
  200.          *
  201.          * A read concern is also not compatible with transactions.
  202.          */
  203.         if (
  204.             ! isset($options['readConcern']) &&
  205.             ! is_in_transaction($options) &&
  206.             ( ! $hasWriteStage || server_supports_feature($serverself::$wireVersionForReadConcernWithWriteStage))
  207.         ) {
  208.             $options['readConcern'] = $this->readConcern;
  209.         }
  210.         if (! isset($options['typeMap'])) {
  211.             $options['typeMap'] = $this->typeMap;
  212.         }
  213.         if ($hasWriteStage && ! isset($options['writeConcern']) && ! is_in_transaction($options)) {
  214.             $options['writeConcern'] = $this->writeConcern;
  215.         }
  216.         $operation = new Aggregate($this->databaseName$this->collectionName$pipeline$options);
  217.         return $operation->execute($server);
  218.     }
  219.     /**
  220.      * Executes multiple write operations.
  221.      *
  222.      * @see BulkWrite::__construct() for supported options
  223.      * @param array[] $operations List of write operations
  224.      * @param array   $options    Command options
  225.      * @return BulkWriteResult
  226.      * @throws UnsupportedException if options are not supported by the selected server
  227.      * @throws InvalidArgumentException for parameter/option parsing errors
  228.      * @throws DriverRuntimeException for other driver errors (e.g. connection errors)
  229.      */
  230.     public function bulkWrite(array $operations, array $options = [])
  231.     {
  232.         if (! isset($options['writeConcern']) && ! is_in_transaction($options)) {
  233.             $options['writeConcern'] = $this->writeConcern;
  234.         }
  235.         $operation = new BulkWrite($this->databaseName$this->collectionName$operations$options);
  236.         $server select_server($this->manager$options);
  237.         return $operation->execute($server);
  238.     }
  239.     /**
  240.      * Gets the number of documents matching the filter.
  241.      *
  242.      * @see Count::__construct() for supported options
  243.      * @param array|object $filter  Query by which to filter documents
  244.      * @param array        $options Command options
  245.      * @return integer
  246.      * @throws UnexpectedValueException if the command response was malformed
  247.      * @throws UnsupportedException if options are not supported by the selected server
  248.      * @throws InvalidArgumentException for parameter/option parsing errors
  249.      * @throws DriverRuntimeException for other driver errors (e.g. connection errors)
  250.      *
  251.      * @deprecated 1.4
  252.      */
  253.     public function count($filter = [], array $options = [])
  254.     {
  255.         if (! isset($options['readPreference']) && ! is_in_transaction($options)) {
  256.             $options['readPreference'] = $this->readPreference;
  257.         }
  258.         $server select_server($this->manager$options);
  259.         if (! isset($options['readConcern']) && ! is_in_transaction($options)) {
  260.             $options['readConcern'] = $this->readConcern;
  261.         }
  262.         $operation = new Count($this->databaseName$this->collectionName$filter$options);
  263.         return $operation->execute($server);
  264.     }
  265.     /**
  266.      * Gets the number of documents matching the filter.
  267.      *
  268.      * @see CountDocuments::__construct() for supported options
  269.      * @param array|object $filter  Query by which to filter documents
  270.      * @param array        $options Command options
  271.      * @return integer
  272.      * @throws UnexpectedValueException if the command response was malformed
  273.      * @throws UnsupportedException if options are not supported by the selected server
  274.      * @throws InvalidArgumentException for parameter/option parsing errors
  275.      * @throws DriverRuntimeException for other driver errors (e.g. connection errors)
  276.      */
  277.     public function countDocuments($filter = [], array $options = [])
  278.     {
  279.         if (! isset($options['readPreference']) && ! is_in_transaction($options)) {
  280.             $options['readPreference'] = $this->readPreference;
  281.         }
  282.         $server select_server($this->manager$options);
  283.         if (! isset($options['readConcern']) && ! is_in_transaction($options)) {
  284.             $options['readConcern'] = $this->readConcern;
  285.         }
  286.         $operation = new CountDocuments($this->databaseName$this->collectionName$filter$options);
  287.         return $operation->execute($server);
  288.     }
  289.     /**
  290.      * Create a single index for the collection.
  291.      *
  292.      * @see Collection::createIndexes()
  293.      * @see CreateIndexes::__construct() for supported command options
  294.      * @param array|object $key     Document containing fields mapped to values,
  295.      *                              which denote order or an index type
  296.      * @param array        $options Index and command options
  297.      * @return string The name of the created index
  298.      * @throws UnsupportedException if options are not supported by the selected server
  299.      * @throws InvalidArgumentException for parameter/option parsing errors
  300.      * @throws DriverRuntimeException for other driver errors (e.g. connection errors)
  301.      */
  302.     public function createIndex($key, array $options = [])
  303.     {
  304.         $commandOptionKeys = ['commitQuorum' => 1'maxTimeMS' => 1'session' => 1'writeConcern' => 1];
  305.         $indexOptions array_diff_key($options$commandOptionKeys);
  306.         $commandOptions array_intersect_key($options$commandOptionKeys);
  307.         return current($this->createIndexes([['key' => $key] + $indexOptions], $commandOptions));
  308.     }
  309.     /**
  310.      * Create one or more indexes for the collection.
  311.      *
  312.      * Each element in the $indexes array must have a "key" document, which
  313.      * contains fields mapped to an order or type. Other options may follow.
  314.      * For example:
  315.      *
  316.      *     $indexes = [
  317.      *         // Create a unique index on the "username" field
  318.      *         [ 'key' => [ 'username' => 1 ], 'unique' => true ],
  319.      *         // Create a 2dsphere index on the "loc" field with a custom name
  320.      *         [ 'key' => [ 'loc' => '2dsphere' ], 'name' => 'geo' ],
  321.      *     ];
  322.      *
  323.      * If the "name" option is unspecified, a name will be generated from the
  324.      * "key" document.
  325.      *
  326.      * @see https://mongodb.com/docs/manual/reference/command/createIndexes/
  327.      * @see https://mongodb.com/docs/manual/reference/method/db.collection.createIndex/
  328.      * @see CreateIndexes::__construct() for supported command options
  329.      * @param array[] $indexes List of index specifications
  330.      * @param array   $options Command options
  331.      * @return string[] The names of the created indexes
  332.      * @throws UnsupportedException if options are not supported by the selected server
  333.      * @throws InvalidArgumentException for parameter/option parsing errors
  334.      * @throws DriverRuntimeException for other driver errors (e.g. connection errors)
  335.      */
  336.     public function createIndexes(array $indexes, array $options = [])
  337.     {
  338.         $server select_server($this->manager$options);
  339.         if (! isset($options['writeConcern']) && ! is_in_transaction($options)) {
  340.             $options['writeConcern'] = $this->writeConcern;
  341.         }
  342.         $operation = new CreateIndexes($this->databaseName$this->collectionName$indexes$options);
  343.         return $operation->execute($server);
  344.     }
  345.     /**
  346.      * Deletes all documents matching the filter.
  347.      *
  348.      * @see DeleteMany::__construct() for supported options
  349.      * @see https://mongodb.com/docs/manual/reference/command/delete/
  350.      * @param array|object $filter  Query by which to delete documents
  351.      * @param array        $options Command options
  352.      * @return DeleteResult
  353.      * @throws UnsupportedException if options are not supported by the selected server
  354.      * @throws InvalidArgumentException for parameter/option parsing errors
  355.      * @throws DriverRuntimeException for other driver errors (e.g. connection errors)
  356.      */
  357.     public function deleteMany($filter, array $options = [])
  358.     {
  359.         if (! isset($options['writeConcern']) && ! is_in_transaction($options)) {
  360.             $options['writeConcern'] = $this->writeConcern;
  361.         }
  362.         $operation = new DeleteMany($this->databaseName$this->collectionName$filter$options);
  363.         $server select_server($this->manager$options);
  364.         return $operation->execute($server);
  365.     }
  366.     /**
  367.      * Deletes at most one document matching the filter.
  368.      *
  369.      * @see DeleteOne::__construct() for supported options
  370.      * @see https://mongodb.com/docs/manual/reference/command/delete/
  371.      * @param array|object $filter  Query by which to delete documents
  372.      * @param array        $options Command options
  373.      * @return DeleteResult
  374.      * @throws UnsupportedException if options are not supported by the selected server
  375.      * @throws InvalidArgumentException for parameter/option parsing errors
  376.      * @throws DriverRuntimeException for other driver errors (e.g. connection errors)
  377.      */
  378.     public function deleteOne($filter, array $options = [])
  379.     {
  380.         if (! isset($options['writeConcern']) && ! is_in_transaction($options)) {
  381.             $options['writeConcern'] = $this->writeConcern;
  382.         }
  383.         $operation = new DeleteOne($this->databaseName$this->collectionName$filter$options);
  384.         $server select_server($this->manager$options);
  385.         return $operation->execute($server);
  386.     }
  387.     /**
  388.      * Finds the distinct values for a specified field across the collection.
  389.      *
  390.      * @see Distinct::__construct() for supported options
  391.      * @param string       $fieldName Field for which to return distinct values
  392.      * @param array|object $filter    Query by which to filter documents
  393.      * @param array        $options   Command options
  394.      * @return array
  395.      * @throws UnexpectedValueException if the command response was malformed
  396.      * @throws UnsupportedException if options are not supported by the selected server
  397.      * @throws InvalidArgumentException for parameter/option parsing errors
  398.      * @throws DriverRuntimeException for other driver errors (e.g. connection errors)
  399.      */
  400.     public function distinct(string $fieldName$filter = [], array $options = [])
  401.     {
  402.         if (! isset($options['readPreference']) && ! is_in_transaction($options)) {
  403.             $options['readPreference'] = $this->readPreference;
  404.         }
  405.         if (! isset($options['typeMap'])) {
  406.             $options['typeMap'] = $this->typeMap;
  407.         }
  408.         $server select_server($this->manager$options);
  409.         if (! isset($options['readConcern']) && ! is_in_transaction($options)) {
  410.             $options['readConcern'] = $this->readConcern;
  411.         }
  412.         $operation = new Distinct($this->databaseName$this->collectionName$fieldName$filter$options);
  413.         return $operation->execute($server);
  414.     }
  415.     /**
  416.      * Drop this collection.
  417.      *
  418.      * @see DropCollection::__construct() for supported options
  419.      * @param array $options Additional options
  420.      * @return array|object Command result document
  421.      * @throws UnsupportedException if options are not supported by the selected server
  422.      * @throws InvalidArgumentException for parameter/option parsing errors
  423.      * @throws DriverRuntimeException for other driver errors (e.g. connection errors)
  424.      */
  425.     public function drop(array $options = [])
  426.     {
  427.         if (! isset($options['typeMap'])) {
  428.             $options['typeMap'] = $this->typeMap;
  429.         }
  430.         $server select_server($this->manager$options);
  431.         if (! isset($options['writeConcern']) && ! is_in_transaction($options)) {
  432.             $options['writeConcern'] = $this->writeConcern;
  433.         }
  434.         $encryptedFields $options['encryptedFields']
  435.             ?? get_encrypted_fields_from_driver($this->databaseName$this->collectionName$this->manager)
  436.             ?? get_encrypted_fields_from_server($this->databaseName$this->collectionName$this->manager$server)
  437.             ?? null;
  438.         if ($encryptedFields !== null) {
  439.             // encryptedFields is not passed to the drop command
  440.             unset($options['encryptedFields']);
  441.             $encryptedFields = (array) $encryptedFields;
  442.             (new DropCollection($this->databaseName$encryptedFields['escCollection'] ?? 'enxcol_.' $this->collectionName '.esc'))->execute($server);
  443.             (new DropCollection($this->databaseName$encryptedFields['eccCollection'] ?? 'enxcol_.' $this->collectionName '.ecc'))->execute($server);
  444.             (new DropCollection($this->databaseName$encryptedFields['ecocCollection'] ?? 'enxcol_.' $this->collectionName '.ecoc'))->execute($server);
  445.         }
  446.         $operation = new DropCollection($this->databaseName$this->collectionName$options);
  447.         return $operation->execute($server);
  448.     }
  449.     /**
  450.      * Drop a single index in the collection.
  451.      *
  452.      * @see DropIndexes::__construct() for supported options
  453.      * @param string|IndexInfo $indexName Index name or model object
  454.      * @param array            $options   Additional options
  455.      * @return array|object Command result document
  456.      * @throws UnsupportedException if options are not supported by the selected server
  457.      * @throws InvalidArgumentException for parameter/option parsing errors
  458.      * @throws DriverRuntimeException for other driver errors (e.g. connection errors)
  459.      */
  460.     public function dropIndex($indexName, array $options = [])
  461.     {
  462.         $indexName = (string) $indexName;
  463.         if ($indexName === '*') {
  464.             throw new InvalidArgumentException('dropIndexes() must be used to drop multiple indexes');
  465.         }
  466.         if (! isset($options['typeMap'])) {
  467.             $options['typeMap'] = $this->typeMap;
  468.         }
  469.         $server select_server($this->manager$options);
  470.         if (! isset($options['writeConcern']) && ! is_in_transaction($options)) {
  471.             $options['writeConcern'] = $this->writeConcern;
  472.         }
  473.         $operation = new DropIndexes($this->databaseName$this->collectionName$indexName$options);
  474.         return $operation->execute($server);
  475.     }
  476.     /**
  477.      * Drop all indexes in the collection.
  478.      *
  479.      * @see DropIndexes::__construct() for supported options
  480.      * @param array $options Additional options
  481.      * @return array|object Command result document
  482.      * @throws UnsupportedException if options are not supported by the selected server
  483.      * @throws InvalidArgumentException for parameter/option parsing errors
  484.      * @throws DriverRuntimeException for other driver errors (e.g. connection errors)
  485.      */
  486.     public function dropIndexes(array $options = [])
  487.     {
  488.         if (! isset($options['typeMap'])) {
  489.             $options['typeMap'] = $this->typeMap;
  490.         }
  491.         $server select_server($this->manager$options);
  492.         if (! isset($options['writeConcern']) && ! is_in_transaction($options)) {
  493.             $options['writeConcern'] = $this->writeConcern;
  494.         }
  495.         $operation = new DropIndexes($this->databaseName$this->collectionName'*'$options);
  496.         return $operation->execute($server);
  497.     }
  498.     /**
  499.      * Gets an estimated number of documents in the collection using the collection metadata.
  500.      *
  501.      * @see EstimatedDocumentCount::__construct() for supported options
  502.      * @param array $options Command options
  503.      * @return integer
  504.      * @throws UnexpectedValueException if the command response was malformed
  505.      * @throws UnsupportedException if options are not supported by the selected server
  506.      * @throws InvalidArgumentException for parameter/option parsing errors
  507.      * @throws DriverRuntimeException for other driver errors (e.g. connection errors)
  508.      */
  509.     public function estimatedDocumentCount(array $options = [])
  510.     {
  511.         if (! isset($options['readPreference']) && ! is_in_transaction($options)) {
  512.             $options['readPreference'] = $this->readPreference;
  513.         }
  514.         $server select_server($this->manager$options);
  515.         if (! isset($options['readConcern']) && ! is_in_transaction($options)) {
  516.             $options['readConcern'] = $this->readConcern;
  517.         }
  518.         $operation = new EstimatedDocumentCount($this->databaseName$this->collectionName$options);
  519.         return $operation->execute($server);
  520.     }
  521.     /**
  522.      * Explains explainable commands.
  523.      *
  524.      * @see Explain::__construct() for supported options
  525.      * @see https://mongodb.com/docs/manual/reference/command/explain/
  526.      * @param Explainable $explainable Command on which to run explain
  527.      * @param array       $options     Additional options
  528.      * @return array|object
  529.      * @throws UnsupportedException if explainable or options are not supported by the selected server
  530.      * @throws InvalidArgumentException for parameter/option parsing errors
  531.      * @throws DriverRuntimeException for other driver errors (e.g. connection errors)
  532.      */
  533.     public function explain(Explainable $explainable, array $options = [])
  534.     {
  535.         if (! isset($options['readPreference']) && ! is_in_transaction($options)) {
  536.             $options['readPreference'] = $this->readPreference;
  537.         }
  538.         if (! isset($options['typeMap'])) {
  539.             $options['typeMap'] = $this->typeMap;
  540.         }
  541.         $server select_server($this->manager$options);
  542.         $operation = new Explain($this->databaseName$explainable$options);
  543.         return $operation->execute($server);
  544.     }
  545.     /**
  546.      * Finds documents matching the query.
  547.      *
  548.      * @see Find::__construct() for supported options
  549.      * @see https://mongodb.com/docs/manual/crud/#read-operations
  550.      * @param array|object $filter  Query by which to filter documents
  551.      * @param array        $options Additional options
  552.      * @return Cursor
  553.      * @throws UnsupportedException if options are not supported by the selected server
  554.      * @throws InvalidArgumentException for parameter/option parsing errors
  555.      * @throws DriverRuntimeException for other driver errors (e.g. connection errors)
  556.      */
  557.     public function find($filter = [], array $options = [])
  558.     {
  559.         if (! isset($options['readPreference']) && ! is_in_transaction($options)) {
  560.             $options['readPreference'] = $this->readPreference;
  561.         }
  562.         $server select_server($this->manager$options);
  563.         if (! isset($options['readConcern']) && ! is_in_transaction($options)) {
  564.             $options['readConcern'] = $this->readConcern;
  565.         }
  566.         if (! isset($options['typeMap'])) {
  567.             $options['typeMap'] = $this->typeMap;
  568.         }
  569.         $operation = new Find($this->databaseName$this->collectionName$filter$options);
  570.         return $operation->execute($server);
  571.     }
  572.     /**
  573.      * Finds a single document matching the query.
  574.      *
  575.      * @see FindOne::__construct() for supported options
  576.      * @see https://mongodb.com/docs/manual/crud/#read-operations
  577.      * @param array|object $filter  Query by which to filter documents
  578.      * @param array        $options Additional options
  579.      * @return array|object|null
  580.      * @throws UnsupportedException if options are not supported by the selected server
  581.      * @throws InvalidArgumentException for parameter/option parsing errors
  582.      * @throws DriverRuntimeException for other driver errors (e.g. connection errors)
  583.      */
  584.     public function findOne($filter = [], array $options = [])
  585.     {
  586.         if (! isset($options['readPreference']) && ! is_in_transaction($options)) {
  587.             $options['readPreference'] = $this->readPreference;
  588.         }
  589.         $server select_server($this->manager$options);
  590.         if (! isset($options['readConcern']) && ! is_in_transaction($options)) {
  591.             $options['readConcern'] = $this->readConcern;
  592.         }
  593.         if (! isset($options['typeMap'])) {
  594.             $options['typeMap'] = $this->typeMap;
  595.         }
  596.         $operation = new FindOne($this->databaseName$this->collectionName$filter$options);
  597.         return $operation->execute($server);
  598.     }
  599.     /**
  600.      * Finds a single document and deletes it, returning the original.
  601.      *
  602.      * The document to return may be null if no document matched the filter.
  603.      *
  604.      * @see FindOneAndDelete::__construct() for supported options
  605.      * @see https://mongodb.com/docs/manual/reference/command/findAndModify/
  606.      * @param array|object $filter  Query by which to filter documents
  607.      * @param array        $options Command options
  608.      * @return array|object|null
  609.      * @throws UnexpectedValueException if the command response was malformed
  610.      * @throws UnsupportedException if options are not supported by the selected server
  611.      * @throws InvalidArgumentException for parameter/option parsing errors
  612.      * @throws DriverRuntimeException for other driver errors (e.g. connection errors)
  613.      */
  614.     public function findOneAndDelete($filter, array $options = [])
  615.     {
  616.         $server select_server($this->manager$options);
  617.         if (! isset($options['writeConcern']) && ! is_in_transaction($options)) {
  618.             $options['writeConcern'] = $this->writeConcern;
  619.         }
  620.         if (! isset($options['typeMap'])) {
  621.             $options['typeMap'] = $this->typeMap;
  622.         }
  623.         $operation = new FindOneAndDelete($this->databaseName$this->collectionName$filter$options);
  624.         return $operation->execute($server);
  625.     }
  626.     /**
  627.      * Finds a single document and replaces it, returning either the original or
  628.      * the replaced document.
  629.      *
  630.      * The document to return may be null if no document matched the filter. By
  631.      * default, the original document is returned. Specify
  632.      * FindOneAndReplace::RETURN_DOCUMENT_AFTER for the "returnDocument" option
  633.      * to return the updated document.
  634.      *
  635.      * @see FindOneAndReplace::__construct() for supported options
  636.      * @see https://mongodb.com/docs/manual/reference/command/findAndModify/
  637.      * @param array|object $filter      Query by which to filter documents
  638.      * @param array|object $replacement Replacement document
  639.      * @param array        $options     Command options
  640.      * @return array|object|null
  641.      * @throws UnexpectedValueException if the command response was malformed
  642.      * @throws UnsupportedException if options are not supported by the selected server
  643.      * @throws InvalidArgumentException for parameter/option parsing errors
  644.      * @throws DriverRuntimeException for other driver errors (e.g. connection errors)
  645.      */
  646.     public function findOneAndReplace($filter$replacement, array $options = [])
  647.     {
  648.         $server select_server($this->manager$options);
  649.         if (! isset($options['writeConcern']) && ! is_in_transaction($options)) {
  650.             $options['writeConcern'] = $this->writeConcern;
  651.         }
  652.         if (! isset($options['typeMap'])) {
  653.             $options['typeMap'] = $this->typeMap;
  654.         }
  655.         $operation = new FindOneAndReplace($this->databaseName$this->collectionName$filter$replacement$options);
  656.         return $operation->execute($server);
  657.     }
  658.     /**
  659.      * Finds a single document and updates it, returning either the original or
  660.      * the updated document.
  661.      *
  662.      * The document to return may be null if no document matched the filter. By
  663.      * default, the original document is returned. Specify
  664.      * FindOneAndUpdate::RETURN_DOCUMENT_AFTER for the "returnDocument" option
  665.      * to return the updated document.
  666.      *
  667.      * @see FindOneAndReplace::__construct() for supported options
  668.      * @see https://mongodb.com/docs/manual/reference/command/findAndModify/
  669.      * @param array|object $filter  Query by which to filter documents
  670.      * @param array|object $update  Update to apply to the matched document
  671.      * @param array        $options Command options
  672.      * @return array|object|null
  673.      * @throws UnexpectedValueException if the command response was malformed
  674.      * @throws UnsupportedException if options are not supported by the selected server
  675.      * @throws InvalidArgumentException for parameter/option parsing errors
  676.      * @throws DriverRuntimeException for other driver errors (e.g. connection errors)
  677.      */
  678.     public function findOneAndUpdate($filter$update, array $options = [])
  679.     {
  680.         $server select_server($this->manager$options);
  681.         if (! isset($options['writeConcern']) && ! is_in_transaction($options)) {
  682.             $options['writeConcern'] = $this->writeConcern;
  683.         }
  684.         if (! isset($options['typeMap'])) {
  685.             $options['typeMap'] = $this->typeMap;
  686.         }
  687.         $operation = new FindOneAndUpdate($this->databaseName$this->collectionName$filter$update$options);
  688.         return $operation->execute($server);
  689.     }
  690.     /**
  691.      * Return the collection name.
  692.      *
  693.      * @return string
  694.      */
  695.     public function getCollectionName()
  696.     {
  697.         return $this->collectionName;
  698.     }
  699.     /**
  700.      * Return the database name.
  701.      *
  702.      * @return string
  703.      */
  704.     public function getDatabaseName()
  705.     {
  706.         return $this->databaseName;
  707.     }
  708.     /**
  709.      * Return the Manager.
  710.      *
  711.      * @return Manager
  712.      */
  713.     public function getManager()
  714.     {
  715.         return $this->manager;
  716.     }
  717.     /**
  718.      * Return the collection namespace.
  719.      *
  720.      * @see https://mongodb.com/docs/manual/reference/glossary/#term-namespace
  721.      * @return string
  722.      */
  723.     public function getNamespace()
  724.     {
  725.         return $this->databaseName '.' $this->collectionName;
  726.     }
  727.     /**
  728.      * Return the read concern for this collection.
  729.      *
  730.      * @see https://php.net/manual/en/mongodb-driver-readconcern.isdefault.php
  731.      * @return ReadConcern
  732.      */
  733.     public function getReadConcern()
  734.     {
  735.         return $this->readConcern;
  736.     }
  737.     /**
  738.      * Return the read preference for this collection.
  739.      *
  740.      * @return ReadPreference
  741.      */
  742.     public function getReadPreference()
  743.     {
  744.         return $this->readPreference;
  745.     }
  746.     /**
  747.      * Return the type map for this collection.
  748.      *
  749.      * @return array
  750.      */
  751.     public function getTypeMap()
  752.     {
  753.         return $this->typeMap;
  754.     }
  755.     /**
  756.      * Return the write concern for this collection.
  757.      *
  758.      * @see https://php.net/manual/en/mongodb-driver-writeconcern.isdefault.php
  759.      * @return WriteConcern
  760.      */
  761.     public function getWriteConcern()
  762.     {
  763.         return $this->writeConcern;
  764.     }
  765.     /**
  766.      * Inserts multiple documents.
  767.      *
  768.      * @see InsertMany::__construct() for supported options
  769.      * @see https://mongodb.com/docs/manual/reference/command/insert/
  770.      * @param array[]|object[] $documents The documents to insert
  771.      * @param array            $options   Command options
  772.      * @return InsertManyResult
  773.      * @throws InvalidArgumentException for parameter/option parsing errors
  774.      * @throws DriverRuntimeException for other driver errors (e.g. connection errors)
  775.      */
  776.     public function insertMany(array $documents, array $options = [])
  777.     {
  778.         if (! isset($options['writeConcern']) && ! is_in_transaction($options)) {
  779.             $options['writeConcern'] = $this->writeConcern;
  780.         }
  781.         $operation = new InsertMany($this->databaseName$this->collectionName$documents$options);
  782.         $server select_server($this->manager$options);
  783.         return $operation->execute($server);
  784.     }
  785.     /**
  786.      * Inserts one document.
  787.      *
  788.      * @see InsertOne::__construct() for supported options
  789.      * @see https://mongodb.com/docs/manual/reference/command/insert/
  790.      * @param array|object $document The document to insert
  791.      * @param array        $options  Command options
  792.      * @return InsertOneResult
  793.      * @throws InvalidArgumentException for parameter/option parsing errors
  794.      * @throws DriverRuntimeException for other driver errors (e.g. connection errors)
  795.      */
  796.     public function insertOne($document, array $options = [])
  797.     {
  798.         if (! isset($options['writeConcern']) && ! is_in_transaction($options)) {
  799.             $options['writeConcern'] = $this->writeConcern;
  800.         }
  801.         $operation = new InsertOne($this->databaseName$this->collectionName$document$options);
  802.         $server select_server($this->manager$options);
  803.         return $operation->execute($server);
  804.     }
  805.     /**
  806.      * Returns information for all indexes for the collection.
  807.      *
  808.      * @see ListIndexes::__construct() for supported options
  809.      * @return IndexInfoIterator
  810.      * @throws InvalidArgumentException for parameter/option parsing errors
  811.      * @throws DriverRuntimeException for other driver errors (e.g. connection errors)
  812.      */
  813.     public function listIndexes(array $options = [])
  814.     {
  815.         $operation = new ListIndexes($this->databaseName$this->collectionName$options);
  816.         $server select_server($this->manager$options);
  817.         return $operation->execute($server);
  818.     }
  819.     /**
  820.      * Executes a map-reduce aggregation on the collection.
  821.      *
  822.      * @see MapReduce::__construct() for supported options
  823.      * @see https://mongodb.com/docs/manual/reference/command/mapReduce/
  824.      * @param JavascriptInterface $map     Map function
  825.      * @param JavascriptInterface $reduce  Reduce function
  826.      * @param string|array|object $out     Output specification
  827.      * @param array               $options Command options
  828.      * @return MapReduceResult
  829.      * @throws UnsupportedException if options are not supported by the selected server
  830.      * @throws InvalidArgumentException for parameter/option parsing errors
  831.      * @throws DriverRuntimeException for other driver errors (e.g. connection errors)
  832.      * @throws UnexpectedValueException if the command response was malformed
  833.      */
  834.     public function mapReduce(JavascriptInterface $mapJavascriptInterface $reduce$out, array $options = [])
  835.     {
  836.         $hasOutputCollection = ! is_mapreduce_output_inline($out);
  837.         if (! isset($options['readPreference']) && ! is_in_transaction($options)) {
  838.             $options['readPreference'] = $this->readPreference;
  839.         }
  840.         // Check if the out option is inline because we will want to coerce a primary read preference if not
  841.         if ($hasOutputCollection) {
  842.             $options['readPreference'] = new ReadPreference(ReadPreference::RP_PRIMARY);
  843.         }
  844.         $server select_server($this->manager$options);
  845.         /* A "majority" read concern is not compatible with inline output, so
  846.          * avoid providing the Collection's read concern if it would conflict.
  847.          *
  848.          * A read concern is also not compatible with transactions.
  849.          */
  850.         if (! isset($options['readConcern']) && ! ($hasOutputCollection && $this->readConcern->getLevel() === ReadConcern::MAJORITY) && ! is_in_transaction($options)) {
  851.             $options['readConcern'] = $this->readConcern;
  852.         }
  853.         if (! isset($options['typeMap'])) {
  854.             $options['typeMap'] = $this->typeMap;
  855.         }
  856.         if (! isset($options['writeConcern']) && ! is_in_transaction($options)) {
  857.             $options['writeConcern'] = $this->writeConcern;
  858.         }
  859.         $operation = new MapReduce($this->databaseName$this->collectionName$map$reduce$out$options);
  860.         return $operation->execute($server);
  861.     }
  862.     /**
  863.      * Renames the collection.
  864.      *
  865.      * @see RenameCollection::__construct() for supported options
  866.      * @param string      $toCollectionName New name of the collection
  867.      * @param string|null $toDatabaseName   New database name of the collection. Defaults to the original database.
  868.      * @param array       $options          Additional options
  869.      * @return array|object Command result document
  870.      * @throws UnsupportedException if options are not supported by the selected server
  871.      * @throws InvalidArgumentException for parameter/option parsing errors
  872.      * @throws DriverRuntimeException for other driver errors (e.g. connection errors)
  873.      */
  874.     public function rename(string $toCollectionName, ?string $toDatabaseName null, array $options = [])
  875.     {
  876.         if (! isset($toDatabaseName)) {
  877.             $toDatabaseName $this->databaseName;
  878.         }
  879.         if (! isset($options['typeMap'])) {
  880.             $options['typeMap'] = $this->typeMap;
  881.         }
  882.         $server select_server($this->manager$options);
  883.         if (! isset($options['writeConcern']) && ! is_in_transaction($options)) {
  884.             $options['writeConcern'] = $this->writeConcern;
  885.         }
  886.         $operation = new RenameCollection($this->databaseName$this->collectionName$toDatabaseName$toCollectionName$options);
  887.         return $operation->execute($server);
  888.     }
  889.     /**
  890.      * Replaces at most one document matching the filter.
  891.      *
  892.      * @see ReplaceOne::__construct() for supported options
  893.      * @see https://mongodb.com/docs/manual/reference/command/update/
  894.      * @param array|object $filter      Query by which to filter documents
  895.      * @param array|object $replacement Replacement document
  896.      * @param array        $options     Command options
  897.      * @return UpdateResult
  898.      * @throws UnsupportedException if options are not supported by the selected server
  899.      * @throws InvalidArgumentException for parameter/option parsing errors
  900.      * @throws DriverRuntimeException for other driver errors (e.g. connection errors)
  901.      */
  902.     public function replaceOne($filter$replacement, array $options = [])
  903.     {
  904.         if (! isset($options['writeConcern']) && ! is_in_transaction($options)) {
  905.             $options['writeConcern'] = $this->writeConcern;
  906.         }
  907.         $operation = new ReplaceOne($this->databaseName$this->collectionName$filter$replacement$options);
  908.         $server select_server($this->manager$options);
  909.         return $operation->execute($server);
  910.     }
  911.     /**
  912.      * Updates all documents matching the filter.
  913.      *
  914.      * @see UpdateMany::__construct() for supported options
  915.      * @see https://mongodb.com/docs/manual/reference/command/update/
  916.      * @param array|object $filter  Query by which to filter documents
  917.      * @param array|object $update  Update to apply to the matched documents
  918.      * @param array        $options Command options
  919.      * @return UpdateResult
  920.      * @throws UnsupportedException if options are not supported by the selected server
  921.      * @throws InvalidArgumentException for parameter/option parsing errors
  922.      * @throws DriverRuntimeException for other driver errors (e.g. connection errors)
  923.      */
  924.     public function updateMany($filter$update, array $options = [])
  925.     {
  926.         if (! isset($options['writeConcern']) && ! is_in_transaction($options)) {
  927.             $options['writeConcern'] = $this->writeConcern;
  928.         }
  929.         $operation = new UpdateMany($this->databaseName$this->collectionName$filter$update$options);
  930.         $server select_server($this->manager$options);
  931.         return $operation->execute($server);
  932.     }
  933.     /**
  934.      * Updates at most one document matching the filter.
  935.      *
  936.      * @see UpdateOne::__construct() for supported options
  937.      * @see https://mongodb.com/docs/manual/reference/command/update/
  938.      * @param array|object $filter  Query by which to filter documents
  939.      * @param array|object $update  Update to apply to the matched document
  940.      * @param array        $options Command options
  941.      * @return UpdateResult
  942.      * @throws UnsupportedException if options are not supported by the selected server
  943.      * @throws InvalidArgumentException for parameter/option parsing errors
  944.      * @throws DriverRuntimeException for other driver errors (e.g. connection errors)
  945.      */
  946.     public function updateOne($filter$update, array $options = [])
  947.     {
  948.         if (! isset($options['writeConcern']) && ! is_in_transaction($options)) {
  949.             $options['writeConcern'] = $this->writeConcern;
  950.         }
  951.         $operation = new UpdateOne($this->databaseName$this->collectionName$filter$update$options);
  952.         $server select_server($this->manager$options);
  953.         return $operation->execute($server);
  954.     }
  955.     /**
  956.      * Create a change stream for watching changes to the collection.
  957.      *
  958.      * @see Watch::__construct() for supported options
  959.      * @param array $pipeline List of pipeline operations
  960.      * @param array $options  Command options
  961.      * @return ChangeStream
  962.      * @throws InvalidArgumentException for parameter/option parsing errors
  963.      */
  964.     public function watch(array $pipeline = [], array $options = [])
  965.     {
  966.         if (! isset($options['readPreference']) && ! is_in_transaction($options)) {
  967.             $options['readPreference'] = $this->readPreference;
  968.         }
  969.         $server select_server($this->manager$options);
  970.         /* Although change streams require a newer version of the server than
  971.          * read concerns, perform the usual wire version check before inheriting
  972.          * the collection's read concern. In the event that the server is too
  973.          * old, this makes it more likely that users will encounter an error
  974.          * related to change streams being unsupported instead of an
  975.          * UnsupportedException regarding use of the "readConcern" option from
  976.          * the Aggregate operation class. */
  977.         if (! isset($options['readConcern']) && ! is_in_transaction($options)) {
  978.             $options['readConcern'] = $this->readConcern;
  979.         }
  980.         if (! isset($options['typeMap'])) {
  981.             $options['typeMap'] = $this->typeMap;
  982.         }
  983.         $operation = new Watch($this->manager$this->databaseName$this->collectionName$pipeline$options);
  984.         return $operation->execute($server);
  985.     }
  986.     /**
  987.      * Get a clone of this collection with different options.
  988.      *
  989.      * @see Collection::__construct() for supported options
  990.      * @param array $options Collection constructor options
  991.      * @return Collection
  992.      * @throws InvalidArgumentException for parameter/option parsing errors
  993.      */
  994.     public function withOptions(array $options = [])
  995.     {
  996.         $options += [
  997.             'readConcern' => $this->readConcern,
  998.             'readPreference' => $this->readPreference,
  999.             'typeMap' => $this->typeMap,
  1000.             'writeConcern' => $this->writeConcern,
  1001.         ];
  1002.         return new Collection($this->manager$this->databaseName$this->collectionName$options);
  1003.     }
  1004. }