Skip to content

Commit d7ba99e

Browse files
authored
PHPLIB-53 Add documentation for mapReduce (#419)
PHPLIB-53 Add documentation for mapReduce
1 parent 403cce2 commit d7ba99e

File tree

7 files changed

+347
-4
lines changed

7 files changed

+347
-4
lines changed
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
source:
2+
file: apiargs-MongoDBCollection-common-option.yaml
3+
ref: bypassDocumentValidation
4+
---
5+
source:
6+
file: apiargs-MongoDBCollection-common-option.yaml
7+
ref: collation
8+
---
9+
arg_name: option
10+
name: finalize
11+
type: :php:`MongoDB\\BSON\\Javascript <class.mongodb-bson-javascript>`
12+
description: |
13+
Follows the reduce method and modifies the output.
14+
interface: phpmethod
15+
operation: ~
16+
optional: true
17+
---
18+
arg_name: option
19+
name: jsMode
20+
type: boolean
21+
description: |
22+
Specifies whether to convert intermediate data into BSON format between the
23+
execution of the map and reduce functions. The default is ``false``.
24+
interface: phpmethod
25+
operation: ~
26+
optional: true
27+
---
28+
arg_name: option
29+
name: limit
30+
type: integer
31+
description: |
32+
Specifies a maximum number of documents for the input into the map function.
33+
interface: phpmethod
34+
operation: ~
35+
optional: true
36+
---
37+
source:
38+
file: apiargs-common-option.yaml
39+
ref: maxTimeMS
40+
---
41+
arg_name: option
42+
name: query
43+
type: document
44+
description: |
45+
Specifies the selection criteria using query operators for determining the
46+
documents input to the map function.
47+
interface: phpmethod
48+
operation: ~
49+
optional: true
50+
---
51+
source:
52+
file: apiargs-MongoDBCollection-common-option.yaml
53+
ref: readConcern
54+
---
55+
source:
56+
file: apiargs-MongoDBCollection-common-option.yaml
57+
ref: readPreference
58+
---
59+
arg_name: option
60+
name: scope
61+
type: document
62+
description: |
63+
Specifies global variables that are accessible in the map, reduce, and finalize
64+
functions.
65+
interface: phpmethod
66+
operation: ~
67+
optional: true
68+
---
69+
source:
70+
file: apiargs-MongoDBCollection-method-find-option.yaml
71+
ref: sort
72+
---
73+
source:
74+
file: apiargs-MongoDBCollection-common-option.yaml
75+
ref: typeMap
76+
---
77+
arg_name: option
78+
name: verbose
79+
type: boolean
80+
description: |
81+
Specifies whether to include the timing information in the result information.
82+
The default is ``true``.
83+
interface: phpmethod
84+
operation: ~
85+
optional: true
86+
---
87+
source:
88+
file: apiargs-MongoDBCollection-common-option.yaml
89+
ref: writeConcern
90+
...
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
arg_name: param
2+
name: $map
3+
type: :php:`MongoDB\\BSON\\Javascript <mongodb-bson-javascript>`
4+
description: |
5+
A JavaScript function that associates or "maps" a value with a key and emits
6+
the key and value pair.
7+
interface: phpmethod
8+
operation: ~
9+
optional: false
10+
---
11+
arg_name: param
12+
name: $reduce
13+
type: :php:`MongoDB\\BSON\\Javascript <class.mongodb-bson-javascript>`
14+
description: |
15+
A JavaScript function that "reduces" to a single object all the values
16+
associated with a particular key.
17+
interface: phpmethod
18+
operation: ~
19+
optional: false
20+
---
21+
arg_name: param
22+
name: $out
23+
type: string|document
24+
description: |
25+
Specifies where to output the result of the map-reduce operation. You can
26+
either output to a collection or return the result inline. On a primary member
27+
of a replica set you can output either to a collection or inline, but on a
28+
secondary, only inline output is possible.
29+
interface: phpmethod
30+
operation: ~
31+
optional: false
32+
---
33+
source:
34+
file: apiargs-common-param.yaml
35+
ref: $options
36+
...

docs/reference/class/MongoDBCollection.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ Methods
8787
/reference/method/MongoDBCollection-insertMany
8888
/reference/method/MongoDBCollection-insertOne
8989
/reference/method/MongoDBCollection-listIndexes
90+
/reference/method/MongoDBCollection-mapReduce
9091
/reference/method/MongoDBCollection-replaceOne
9192
/reference/method/MongoDBCollection-updateMany
9293
/reference/method/MongoDBCollection-updateOne
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
=================================
2+
MongoDB\\Collection::mapReduce()
3+
=================================
4+
5+
.. default-domain:: mongodb
6+
7+
.. contents:: On this page
8+
:local:
9+
:backlinks: none
10+
:depth: 1
11+
:class: singlecol
12+
13+
Definition
14+
----------
15+
16+
.. phpmethod:: MongoDB\\Collection::mapReduce()
17+
18+
The :manual:`mapReduce </reference/command/mapReduce>` command allows you to
19+
run map-reduce aggregation operations over a collection.
20+
21+
.. code-block:: php
22+
23+
function mapReduce($map, $reduce, $out, array $options = []): MongoDB\MapReduceResult
24+
25+
This method has the following parameters:
26+
27+
.. include:: /includes/apiargs/MongoDBCollection-method-mapReduce-param.rst
28+
29+
The ``$options`` parameter supports the following options:
30+
31+
.. include:: /includes/apiargs/MongoDBCollection-method-mapReduce-option.rst
32+
33+
Return Values
34+
-------------
35+
36+
A :phpclass:`MongoDB\\MapReduceResult` object, which allows for iteration of
37+
mapReduce results irrespective of the output method (e.g. inline, collection)
38+
via the :php:`IteratorAggregate <iteratoraggregate>` interface. It also
39+
provides access to command statistics.
40+
41+
Errors/Exceptions
42+
-----------------
43+
44+
.. include:: /includes/extracts/error-unsupportedexception.rst
45+
.. include:: /includes/extracts/error-invalidargumentexception.rst
46+
.. include:: /includes/extracts/error-unexpectedvalueexception.rst
47+
.. include:: /includes/extracts/error-driver-runtimeexception.rst
48+
49+
Behavior
50+
--------
51+
52+
In MongoDB, the map-reduce operation can write results to a collection
53+
or return the results inline. If you write map-reduce output to a
54+
collection, you can perform subsequent map-reduce operations on the
55+
same input collection that merge replace, merge, or reduce new results
56+
with previous results. See :manual:`Map-Reduce </core/map-reduce>` and
57+
:manual:`Perform Incremental Map-Reduce </tutorial/perform-incremental-map-reduce>`
58+
for details and examples.
59+
60+
When returning the results of a map-reduce operation *inline*, the
61+
result documents must be within the :limit:`BSON Document Size` limit,
62+
which is currently 16 megabytes.
63+
64+
MongoDB supports map-reduce operations on :manual:`sharded collections
65+
</sharding>`. Map-reduce operations can also output
66+
the results to a sharded collection. See
67+
:manual:`Map-Reduce and Sharded Collections </core/map-reduce-sharded-collections>`.
68+
69+
Example
70+
-------
71+
72+
This example will use city populations to calculate the overall population of
73+
each state.
74+
75+
.. code-block:: php
76+
77+
<?php
78+
79+
$collection = (new MongoDB\Client)->test->zips;
80+
81+
$map = new MongoDB\BSON\Javascript('function() { emit(this.state, this.pop); }');
82+
$reduce = new MongoDB\BSON\Javascript('function(key, values) { return Array.sum(values) }');
83+
$out = ['inline' => 1];
84+
85+
$populations = $collection->mapReduce($map, $reduce, $out);
86+
87+
foreach ($populations as $pop) {
88+
var_dump($pop);
89+
};
90+
91+
The output would then resemble::
92+
93+
object(stdClass)#2293 (2) {
94+
["_id"]=>
95+
string(2) "AK"
96+
["value"]=>
97+
float(544698)
98+
}
99+
object(stdClass)#2300 (2) {
100+
["_id"]=>
101+
string(2) "AL"
102+
["value"]=>
103+
float(4040587)
104+
}
105+
object(stdClass)#2293 (2) {
106+
["_id"]=>
107+
string(2) "AR"
108+
["value"]=>
109+
float(2350725)
110+
}
111+
object(stdClass)#2300 (2) {
112+
["_id"]=>
113+
string(2) "AZ"
114+
["value"]=>
115+
float(3665228)
116+
}
117+
118+
119+
See Also
120+
--------
121+
122+
- :manual:`mapReduce </reference/command/mapReduce>` command reference in the MongoDB
123+
manual
124+
- :manual:`Map-Reduce </core/map-reduce>` documentation in the MongoDB manual
125+

src/Collection.php

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
namespace MongoDB;
1919

20+
use MongoDB\BSON\JavascriptInterface;
2021
use MongoDB\Driver\Cursor;
2122
use MongoDB\Driver\Manager;
2223
use MongoDB\Driver\ReadConcern;
@@ -44,6 +45,7 @@
4445
use MongoDB\Operation\InsertMany;
4546
use MongoDB\Operation\InsertOne;
4647
use MongoDB\Operation\ListIndexes;
48+
use MongoDB\Operation\MapReduce;
4749
use MongoDB\Operation\ReplaceOne;
4850
use MongoDB\Operation\UpdateMany;
4951
use MongoDB\Operation\UpdateOne;
@@ -809,6 +811,56 @@ public function listIndexes(array $options = [])
809811
return $operation->execute($server);
810812
}
811813

814+
/**
815+
* Executes a map-reduce aggregation on the collection.
816+
*
817+
* @see MapReduce::__construct() for supported options
818+
* @see http://docs.mongodb.org/manual/reference/command/mapReduce/
819+
* @param JavascriptInterface $map Map function
820+
* @param JavascriptInterface $reduce Reduce function
821+
* @param string|array|object $out Output specification
822+
* @param array $options Command options
823+
* @return MapReduceResult
824+
* @throws UnsupportedException if options are not supported by the selected server
825+
* @throws InvalidArgumentException for parameter/option parsing errors
826+
* @throws DriverRuntimeException for other driver errors (e.g. connection errors)
827+
* @throws UnexpectedValueException if the command response was malformed
828+
*/
829+
public function mapReduce(JavascriptInterface $map, JavascriptInterface $reduce, $out, array $options = [])
830+
{
831+
$hasOutputCollection = ! $this->isOutInline($out);
832+
833+
if ( ! isset($options['readPreference'])) {
834+
$options['readPreference'] = $this->readPreference;
835+
}
836+
837+
// Check if the out option is inline because we will want to coerce a primary read preference if not
838+
if ($hasOutputCollection) {
839+
$options['readPreference'] = new ReadPreference(ReadPreference::RP_PRIMARY);
840+
}
841+
842+
$server = $this->manager->selectServer($options['readPreference']);
843+
844+
/* A "majority" read concern is not compatible with inline output, so
845+
* avoid providing the Collection's read concern if it would conflict.
846+
*/
847+
if ( ! isset($options['readConcern']) && ! ($hasOutputCollection && $this->readConcern->getLevel() === ReadConcern::MAJORITY) && \MongoDB\server_supports_feature($server, self::$wireVersionForReadConcern)) {
848+
$options['readConcern'] = $this->readConcern;
849+
}
850+
851+
if ( ! isset($options['typeMap'])) {
852+
$options['typeMap'] = $this->typeMap;
853+
}
854+
855+
if (! isset($options['writeConcern']) && \MongoDB\server_supports_feature($server, self::$wireVersionForWritableCommandWriteConcern)) {
856+
$options['writeConcern'] = $this->writeConcern;
857+
}
858+
859+
$operation = new MapReduce($this->databaseName, $this->collectionName, $map, $reduce, $out, $options);
860+
861+
return $operation->execute($server);
862+
}
863+
812864
/**
813865
* Replaces at most one document matching the filter.
814866
*
@@ -903,4 +955,19 @@ public function withOptions(array $options = [])
903955

904956
return new Collection($this->manager, $this->databaseName, $this->collectionName, $options);
905957
}
958+
959+
private function isOutInline($out)
960+
{
961+
if ( ! is_array($out) && ! is_object($out)) {
962+
return false;
963+
}
964+
965+
$out = (array) $out;
966+
967+
if (key($out) === 'inline') {
968+
return true;
969+
}
970+
971+
return false;
972+
}
906973
}

src/Operation/MapReduce.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
namespace MongoDB\Operation;
1919

20-
use MongoDB\BSON\Javascript;
20+
use MongoDB\BSON\JavascriptInterface;
2121
use MongoDB\Driver\Command;
2222
use MongoDB\Driver\ReadConcern;
2323
use MongoDB\Driver\ReadPreference;
@@ -130,13 +130,13 @@ class MapReduce implements Executable
130130
*
131131
* @param string $databaseName Database name
132132
* @param string $collectionName Collection name
133-
* @param Javascript $map Map function
134-
* @param Javascript $reduce Reduce function
133+
* @param JavascriptInterface $map Map function
134+
* @param JavascriptInterface $reduce Reduce function
135135
* @param string|array|object $out Output specification
136136
* @param array $options Command options
137137
* @throws InvalidArgumentException for parameter/option parsing errors
138138
*/
139-
public function __construct($databaseName, $collectionName, Javascript $map, Javascript $reduce, $out, array $options = [])
139+
public function __construct($databaseName, $collectionName, JavascriptInterface $map, JavascriptInterface $reduce, $out, array $options = [])
140140
{
141141
if ( ! is_string($out) && ! is_array($out) && ! is_object($out)) {
142142
throw InvalidArgumentException::invalidType('$out', $out, 'string or array or object');

0 commit comments

Comments
 (0)