# db.collection.mapReduce()

在本页面

* [map功能要求](#requirements-for-the-map-function)
* [reduce功能要求](#requirements-for-the-reduce-function)
* [选项](#out-options)
* [finalize功能要求](#requirements-for-the-finalize-function)
* [Map-Reduce 例子](#map-reduce-examples)
* [输出](#output)
* [附加信息](#additional-information)

`db.collection. mapReduce`( map，reduce，{\<out>，\<query>，\<sort>，\<limit>，\<finalize>，\<scope>，\<jsMode>，\<verbose>})

> **注意**
>
> 从4.2版开始，MongoDB弃用：
>
> * 地图-reduce选项来\_创建\_一个新的分片集合以及使用的分片供选择的map-reduce。要输出到分片集合，请首先创建分片集合。MongoDB 4.2还不建议替换现有分片集合。
> * nonAtomic：false选项的显式规范。

db.collection.mapReduce()方法为MapReduce命令提供了包装。

> **注意**
>
> 视图不支持 map-reduce 操作。

db.collection.mapReduce()具有以下语法：

```
db.collection.mapReduce(
    <map>,
    <reduce>,
    {
        out: <collection>,
        query: <document>,
        sort: <document>,
        limit: <number>,
        finalize: <function>,
        scope: <document>,
        jsMode: <boolean>,
        verbose: <boolean>,
        bypassDocumentValidation: <boolean>
    }
)
```

db.collection.mapReduce()采用以下参数：

| 参数                         | 类型       | 描述                                                                                           |
| -------------------------- | -------- | -------------------------------------------------------------------------------------------- |
| `map`                      | function | 一个 JavaScript function 将与`key`关联或“maps”并发出`key`和 value `pair`。 有关详细信息，请参阅map Function 的要求。   |
| `reduce`                   | function | 一个 JavaScript function，它“减少”到一个 object 所有与特定`key`关联的`values`。 有关详细信息，请参阅reduce Function 的要求。 |
| `options`                  | document | 为db.collection.mapReduce()指定其他参数的文档。                                                         |
| `bypassDocumentValidation` | boolean  | 可选的。允许MapReduce在操作期间绕过文档验证。这使您可以插入不符合验证要求的文档。 version 3.2 中的新内容。                             |

下表描述了db.collection.mapReduce()可以接受的其他参数。

| 领域          | 类型                 | 描述                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| ----------- | ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `out`       | string or document | 指定 map-reduce 操作结果的位置。您可以输出到集合，输出到具有操作的集合，或输出内联。在对集合的主要成员执行 map-reduce 操作时，您可以输出到集合;在次要成员上，您只能使用`inline`输出。 有关详细信息，请参阅选项。                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `query`     | document           | 使用query operators指定选择条件，以确定输入到`map` function 的文档。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `sort`      | document           | 对输入文档进行排序。此选项对优化很有用。对于 example，请将 sort key 指定为与 emit key 相同，以便减少 reduce 操作。 sort key 必须位于此集合的现有索引中。                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `limit`     | number             | 指定输入`map` function 的最大文档数。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `finalize`  | function           | 可选的。遵循`reduce`方法并修改输出。 有关详细信息，请参阅finalize Function 的要求。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| `scope`     | document           | 指定`map`，`reduce`和`finalize`函数中可访问的 global 变量。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `jsMode`    | boolean            | 指定是否在执行`map`和`reduce`函数之间将中间数据转换为 BSON 格式。 默认为`false`。 如果`false`： 1. 在内部，MongoDB 将`map` function 发出的 JavaScript objects 转换为 BSON objects。然后在调用`reduce` function 时将这些 BSON objects 转换回 JavaScript objects。 2. map-reduce 操作将中间 BSON object 放置在临时的 on-disk 存储中。这允许 map-reduce 操作在任意大的数据集上执行。 如果`true`： 1. 在内部，`map` function 期间发出的 JavaScript objects 仍然是 JavaScript objects。无需为`reduce` function 转换 objects，这可以加快执行速度。 2. 您只能将`jsMode`用于映射器`emit()` function 中少于 500,000 个不同`key` arguments 的结果\_set。                                                                 |
| `verbose`   | boolean            | 指定是否在结果信息中包含`timing`信息。将`verbose`设置为`true`以包含`timing`信息。 默认为`false`。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `collation` | document           | 可选的。 指定要用于操作的排序规则。 整理允许用户为 string 比较指定 language-specific 规则，例如字母和重音标记的规则。 排序规则选项具有以下语法： 排序规则：{ locale：\<string>， caseLevel：\<boolean>， caseFirst：\<string>， strength：\<int>， numericOrdering：\<boolean>， alternate：\<string>， maxVariable：\<string>， backwards ：\<boolean> } 指定排序规则时，`locale`字段是必填字段;所有其他校对字段都是可选的。有关字段的说明，请参阅整理文件。 如果未指定排序规则但集合具有默认排序规则(请参阅db.createCollection())，则操作将使用为集合指定的排序规则。 如果没有为集合或操作指定排序规则，MongoDB 使用先前版本中用于 string 比较的简单二进制比较。 您无法为操作指定多个排序规则。对于 example，您不能为每个字段指定不同的排序规则，或者如果使用排序执行查找，则不能对查找使用一个排序规则，而对排序使用另一个排序规则。 version 3.4 中的新内容。 |

> **注意**
>
> map-reduce operations， group 命令和$where 运算表达式无法访问 mongo shell 中可用的某些 global 函数或 properties，例如 db。 可用的 PropertiesAvailable 函数

以下JavaScript函数和属性**可**用于 和 运算符表达式：`map-reduce operations`、`$where`

| 可用属性                     | 可用功能                                                                                                                                                                                                                                                                                                                                                     |
| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `args` `MaxKey` `MinKey` | `assert()` `BinData()` `DBPointer()` `DBRef()` `doassert()` `emit()` `gc()` `HexData()` `hex_md5()` `isNumber()` `isObject()` `ISODate()` `isString()` `Map()` `MD5()` `NumberInt()` `NumberLong()` `ObjectId()` `print()` `printjson()` `printjsononeline()` `sleep()` `Timestamp()` `tojson()` `tojsononeline()` `tojsonObject()` `UUID()` `version()` |

## map功能要求

`map` function 负责将每个输入文档转换为零个或多个文档。它可以访问`scope`参数中定义的变量，并具有以下原型：

```
function() {
    ...
    emit(key, value);
}
```

`map` function 具有以下要求：

* 在`map` function 中，在 function 中将当前文档作为`this`引用。
* `map` function 不应出于任何原因访问数据库。
* `map` function 应该是纯的，或者在 function 之外没有影响(即：side effects.)
* 单个发射只能容纳 MongoDB 的最大 BSON 文件大小的一半。
* `map` function 可以选择多次调用`emit(key,value)`来创建一个将`key`与`value`相关联的输出文档。
* 在MongoDB 4.2和更早版本中，单个发射只能容纳MongoDB 最大BSON文档大小的一半。从版本4.4开始，MongoDB删除了此限制。
* 从MongoDB 4.4开始，它的功能`mapReduce`不再支持范围（即BSON类型15）的已弃用JavaScript 。该`map` 函数必须是BSON类型的String（即BSON类型2）或BSON类型的JavaScript（即BSON类型13）。要确定变量的范围，请使用 `scope`参数。

`map`自版本4.2.1起，该功能不建议在范围内使用JavaScript

以下`map` function 将调用`emit(key,value)` 0 或 1 次，具体取决于输入文档的`status`字段的 value：

```
function() {
    if (this.status == 'A')
    emit(this.cust_id, 1);
}
```

以下`map` function 可能会多次调用`emit(key,value)`，具体取决于输入文档的`items`字段中的元素数：

```
function() {
    this.items.forEach(function(item){ emit(item.sku, 1); });
}
```

## reduce功能要求

`reduce` function 具有以下原型：

```
function(key, values) {
    ...
    return result;
}
```

`reduce` function 表现出以下行为：

* `reduce` function 不应该访问数据库，甚至不应该执行读操作。
* `reduce` function 不应影响外部系统。
* MongoDB 不会为只有一个 value 的 key 调用`reduce` function。 `values`参数是一个 array，其元素是`value` objects，它们被“映射”到`key`。
* MongoDB 可以为同一个 key 多次调用`reduce` function。在这种情况下，该 key 的`reduce` function 的前一个输出将成为该 key 的下一个`reduce` function 调用的输入值之一。
* `reduce` function 可以访问`scope`参数中定义的变量。
* `reduce`的输入不得大于 MongoDB 的最大 BSON 文件大小的一半。返回大型文档然后在后续的`reduce`步骤中将其连接在一起时，可能会违反此要求。
* 从版本4.2.1开始，MongoDB在该功能的作用域（即BSON类型15）中弃用JavaScript `reduce`。要确定变量的范围，请改用`scope` 参数。

因为可以为同一个 key 多次调用`reduce` function，所以以下 properties 需要 true：

* return object 的类型必须与`map` function 发出的`value`的类型相同。
* `reduce` function 必须是关联的。以下语句必须是 true：

  ```
    reduce(key, [ C, reduce(key, [ A, B ]) ] ) == reduce( key, [ C, A, B ] )
  ```
* `reduce` function 必须是幂等的。确保以下语句是 true：

  ```
    reduce( key, [ reduce(key, valuesArray) ] ) ==     reduce( key, valuesArray )
  ```
* `reduce` function 应该是可交换的：也就是说，`valuesArray`中元素的 order 不应该影响`reduce` function 的输出，因此以下语句是 true：

  ```
  reduce( key, [ A, B ] ) == reduce( key, [ B, A ] )
  ```

## 选项

您可以为`out`参数指定以下选项：

### 输出到集合

此选项输出到新集合，并且在副本集的辅助成员上不可用。

```
out: <collectionName>
```

### 输出到带有 Action 的 Collection

> **注意**
>
> 从4.2版开始，MongoDB弃用：
>
> * 地图-reduce选项来\_创建\_一个新的分片集合以及使用的分片供选择的map-reduce。要输出到分片集合，请首先创建分片集合。MongoDB 4.2还不建议替换现有分片集合。
> * nonAtomic：false选项的显式规范。

此选项仅在将已存在的集合传递给`out`时可用。它不适用于副本集 的辅助成员。

```
out: { <action>: <collectionName>
    [, db: <dbName>]
    [, sharded: <boolean> ]
    [, nonAtomic: <boolean> ] }
```

当您输出带有操作的集合时，`out`具有以下参数：

* `<action>`：指定以下操作之一：
  * `replace`

    如果具有`<collectionName>`的集合存在，则替换`<collectionName>`的内容。
  * `merge`

    如果输出集合已存在，则将新结果与现有结果合并。如果现有文档与新结果具有相同的 key，则覆盖该现有文档。
  * `reduce`

    如果输出集合已存在，则将新结果与现有结果合并。如果现有文档与新结果具有相同的 key，则将`reduce` function 应用于新文档和现有文档，并使用结果覆盖现有文档。
* `db` :

  可选的。您希望 map-reduce 操作写入其输出的数据库的 name。默认情况下，这将是与输入集合相同的数据库。
* `sharded` :

  可选的。如果`true`并且您已在输出数据库上启用了分片，则 map-reduce 操作将使用`_id`字段分割输出集合作为分片 key。

  如果`true`和`collectionName`是现有的未整数集合，map-reduce 将失败。
* `nonAtomic` :

  > **注意**
  >
  > 开始在MongoDB中4.2，明确设置`nonAtomic`到`false`已被弃用。

  可选的。将输出操作指定为 non-atomic。这仅对\*\*`merge`和`reduce`输出模式应用\*\*，这可能需要几分钟才能执行。

  默认情况下`nonAtomic`是`false`，map-reduce 操作在 post-processing 期间锁定数据库。

  如果`nonAtomic`是`true`，则 post-processing step 会阻止 MongoDB 锁定数据库：在此 time 期间，其他 clients 将能够读取输出集合的中间状态。

### 输出内联

在 memory 中执行 map-reduce 操作并 return 结果。此选项是副本集的辅助成员上`out`的唯一可用选项。

```
out: { inline: 1 }
```

结果必须符合BSON 文档的最大大小。

## finalize功能要求

`finalize` function 具有以下原型：

```
function(key, reducedValue) {
    ...
    return modifiedObject;
}
```

`finalize` function 接收value 作为其 arguments 和`reduce` function 的`reducedValue`。意识到：

* `finalize` function 不应出于任何原因访问数据库。
* `finalize` function 应该是纯的，或者在 function 之外没有影响(即：side effects.)
* `finalize` function 可以访问`scope`参数中定义的变量。
* 从版本4.2.1开始，MongoDB在该功能的作用域（即BSON类型15）中弃用JavaScript `finalize`。要确定变量的范围，请改用`scope` 参数。

## Map-Reduce 例子

> 聚合管道作为替代
>
> 聚合管道比map-reduce提供更好的性能和更一致的接口。
>
> 各种map-reduce表达式可以使用被重写聚合管道运算符，诸如`$group`， `$merge`等
>
> 下面的示例包括聚合管道备选方案。

`orders`使用以下文档创建样本集合：

```
db.orders.insertMany([
   { _id: 1, cust_id: "Ant O. Knee", ord_date: new Date("2020-03-01"), price: 25, items: [ { sku: "oranges", qty: 5, price: 2.5 }, { sku: "apples", qty: 5, price: 2.5 } ], status: "A" },
   { _id: 2, cust_id: "Ant O. Knee", ord_date: new Date("2020-03-08"), price: 70, items: [ { sku: "oranges", qty: 8, price: 2.5 }, { sku: "chocolates", qty: 5, price: 10 } ], status: "A" },
   { _id: 3, cust_id: "Busby Bee", ord_date: new Date("2020-03-08"), price: 50, items: [ { sku: "oranges", qty: 10, price: 2.5 }, { sku: "pears", qty: 10, price: 2.5 } ], status: "A" },
   { _id: 4, cust_id: "Busby Bee", ord_date: new Date("2020-03-18"), price: 25, items: [ { sku: "oranges", qty: 10, price: 2.5 } ], status: "A" },
   { _id: 5, cust_id: "Busby Bee", ord_date: new Date("2020-03-19"), price: 50, items: [ { sku: "chocolates", qty: 5, price: 10 } ], status: "A"},
   { _id: 6, cust_id: "Cam Elot", ord_date: new Date("2020-03-19"), price: 35, items: [ { sku: "carrots", qty: 10, price: 1.0 }, { sku: "apples", qty: 10, price: 2.5 } ], status: "A" },
   { _id: 7, cust_id: "Cam Elot", ord_date: new Date("2020-03-20"), price: 25, items: [ { sku: "oranges", qty: 10, price: 2.5 } ], status: "A" },
   { _id: 8, cust_id: "Don Quis", ord_date: new Date("2020-03-20"), price: 75, items: [ { sku: "chocolates", qty: 5, price: 10 }, { sku: "apples", qty: 10, price: 2.5 } ], status: "A" },
   { _id: 9, cust_id: "Don Quis", ord_date: new Date("2020-03-20"), price: 55, items: [ { sku: "carrots", qty: 5, price: 1.0 }, { sku: "apples", qty: 10, price: 2.5 }, { sku: "oranges", qty: 10, price: 2.5 } ], status: "A" },
   { _id: 10, cust_id: "Don Quis", ord_date: new Date("2020-03-23"), price: 25, items: [ { sku: "oranges", qty: 10, price: 2.5 } ], status: "A" }
])
```

### 返回每位客户的总价格

通过`cust_id`对`orders`集合执行 map-reduce 操作到 group，并为每个`cust_id`计算`price`的总和：

1. 定义map功能来处理每个输入文档：
2. 在 function 中，`this`指的是 map-reduce 操作正在处理的文档。
3. function maps 为每个文档的`cust_id`并发出`cust_id`和`price`键值对。

   ```
   var mapFunction1 = function() {
       emit(this.cust_id, this.price);
   };
   ```
4. 使用两个参数 `keyCustId`和`valuesPrices`定义相应的 reduce function：
5. `valuesPrices`是一个数组，其元素是 map function 发出的`price`值，并按`keyCustId`分组。
6. function 将`valuesPrice` array 缩减为其元素的总和。

   ```
   var reduceFunction1 = function(keyCustId, valuesPrices) {
       return Array.sum(valuesPrices);
   };
   ```
7. 使用`mapFunction1` map function 和`reduceFunction1` reduce function 对`orders`集合中的所有文档执行 map-reduce。

   ```
    db.orders.mapReduce(
        mapFunction1,
        reduceFunction1,
        { out: "map_reduce_example" }
    )
   ```

   此操作将结果输出到名为`map_reduce_example`的集合。如果`map_reduce_example`集合已存在，则操作将使用此 map-reduce 操作的结果替换内容。
8. 查询`map_reduce_example`集合以验证结果：

   ```
    db.map_reduce_example.find().sort( { _id: 1 } )
   ```

   该操作返回以下文档：

   ```
    { "_id" : "Ant O. Knee", "value" : 95 }
    { "_id" : "Busby Bee", "value" : 125 }
    { "_id" : "Cam Elot", "value" : 60 }
    { "_id" : "Don Quis", "value" : 155 }
   ```

#### 聚合替代

使用可用的聚合管道运算符，您可以重写map-reduce操作，而无需定义自定义函数：

```
db.orders.aggregate([
   { $group: { _id: "$cust_id", value: { $sum: "$price" } } },
   { $out: "agg_alternative_1" }
])
```

1. `$group`由平台组`cust_id`并计算`value`字段（参见`$sum`）。该 `value`字段包含`price`每个的总计`cust_id`。

   该阶段将以下文档输出到下一阶段：

   ```
   { "_id" : "Don Quis", "value" : 155 }
   { "_id" : "Ant O. Knee", "value" : 95 }
   { "_id" : "Cam Elot", "value" : 60 }
   { "_id" : "Busby Bee", "value" : 125 }
   ```
2. 然后，`$out`将输出写入collection `agg_alternative_1`。或者，您可以使用 `$merge`代替`$out`。
3. 查询`agg_alternative_1`集合以验证结果：

   ```
   db.agg_alternative_1.find().sort( { _id: 1 } )
   ```

   该操作返回以下文档：

   ```
   { "_id" : "Ant O. Knee", "value" : 95 }
   { "_id" : "Busby Bee", "value" : 125 }
   { "_id" : "Cam Elot", "value" : 60 }
   { "_id" : "Don Quis", "value" : 155 }
   ```

### 使用 Item 的平均数量计算 Order 和总数量

在此事例中，您将对`orders`集合执行 map-reduce 操作，以处理`ord_date` value 大于`01/01/2012`的所有文档。操作按`item.sku`字段分组，并计算每个`sku`的订单数量和订购总数量。然后，该操作将为每个值计算每个订单的平均数量，并将结果合并到输出集合中。合并结果时，如果现有文档的密钥与新结果相同，则该操作将覆盖现有文档。如果不存在具有相同密钥的文档，则该操作将插入该文档。

1. 定义map功能来处理每个输入文档：
2. 在 function 中，`this`指的是 map-reduce 操作正在处理的文档。
3. 对于每个 item，函数将`sku`与一个新的 object `value`相关联，该对象 `value`包含订单的`count`和\_ite用于 order 并发出`sku`和`value`对。

   ```
   var mapFunction2 = function() {
       for (var idx = 0; idx < this.items.length; idx++) {
           var key = this.items[idx].sku;
           var value = {
               count: 1,
               qty: this.items[idx].qty
           };
           emit(key, value);
       }
   };
   ```
4. 使用两个 arguments `keySKU`和`countObjVals`定义相应的 reduce function：
5. `countObjVals`是一个 array，其元素是映射到 map function 传递给 reducer function 的分组`keySKU`值的 objects。
6. function 将`countObjVals` array 缩减为包含`count`和`qty`字段的单个 object `reducedValue`。
7. 在`reducedVal`中，`count`字段包含来自各个 array 元素的`count`字段的总和，`qty`字段包含来自各个 array 元素的`qty`字段的总和。

   ```
   var reduceFunction2 = function(keySKU, countObjVals) {
   reducedVal = { count: 0, qty: 0 };
       for (var idx = 0; idx < countObjVals.length; idx++) {
           reducedVal.count += countObjVals[idx].count;
           reducedVal.qty += countObjVals[idx].qty;
       }

       return reducedVal;
   };
   ```
8. 使用两个 arguments `key`和`reducedVal`定义 finalize function。 function 修改`reducedVal` object 以添加名为`avg`的计算字段并返回修改后的 object：

   ```
    var finalizeFunction2 = function (key, reducedVal) {
        reducedVal.avg = reducedVal.qty/reducedVal.count;

        return reducedVal;

    };
   ```
9. 使用`mapFunction2`，`reduceFunction2`和`finalizeFunction2`函数对`orders`集合执行 map-reduce 操作。

   ```
   db.orders.mapReduce( mapFunction2,
       reduceFunction2,
       {
           out: { merge: "map_reduce_example" },
           query: { ord_date:
               { $gt: new Date('01/01/2012') }
           },
           finalize: finalizeFunction2
       }
   )
   ```

   此操作使用`query`字段仅选择`ord_date`大于`new Date(01/01/2012)`的文档。然后它将结果输出到集合`map_reduce_example`。如果`map_reduce_example`集合已存在，则操作将现有内容与此 map-reduce 操作的结果合并。也就是说，如果现有文档具有与新结果相同的密钥，则该操作将覆盖现有文档。如果不存在具有相同密钥的文档，则该操作将插入该文档。
10. 查询`map_reduce_example2`集合以验证结果：

    ```
    db.map_reduce_example2.find().sort( { _id: 1 } )
    ```

    该操作返回以下文档：

    ```
    { "_id" : "apples", "value" : { "count" : 3, "qty" : 30, "avg" : 10 } }
    { "_id" : "carrots", "value" : { "count" : 2, "qty" : 15, "avg" : 7.5 } }
    { "_id" : "chocolates", "value" : { "count" : 3, "qty" : 15, "avg" : 5 } }
    { "_id" : "oranges", "value" : { "count" : 6, "qty" : 58, "avg" : 9.666666666666666 } }
    { "_id" : "pears", "value" : { "count" : 1, "qty" : 10, "avg" : 10 } }
    ```

#### 聚合替代

使用可用的聚合管道运算符，您可以重写map-reduce操作，而无需定义自定义函数：

```
db.orders.aggregate( [
   { $match: { ord_date: { $gte: new Date("2020-03-01") } } },
   { $unwind: "$items" },
   { $group: { _id: "$items.sku", qty: { $sum: "$items.qty" }, orders_ids: { $addToSet: "$_id" } }  },
   { $project: { value: { count: { $size: "$orders_ids" }, qty: "$qty", avg: { $divide: [ "$qty", { $size: "$orders_ids" } ] } } } },
   { $merge: { into: "agg_alternative_3", on: "_id", whenMatched: "replace",  whenNotMatched: "insert" } }
] )
```

1. 该`$match`阶段仅选择`ord_date`大于或等于的那些文档。`new Date("2020-03-01")`
2. 该`$unwinds`阶段按`items`数组字段细分文档，以输出每个数组元素的文档。例如：

   ```
   { "_id" : 1, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-01T00:00:00Z"), "price" : 25, "items" : { "sku" : "oranges", "qty" : 5, "price" : 2.5 }, "status" : "A" }
   { "_id" : 1, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-01T00:00:00Z"), "price" : 25, "items" : { "sku" : "apples", "qty" : 5, "price" : 2.5 }, "status" : "A" }
   { "_id" : 2, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 70, "items" : { "sku" : "oranges", "qty" : 8, "price" : 2.5 }, "status" : "A" }
   { "_id" : 2, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 70, "items" : { "sku" : "chocolates", "qty" : 5, "price" : 10 }, "status" : "A" }
   { "_id" : 3, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 50, "items" : { "sku" : "oranges", "qty" : 10, "price" : 2.5 }, "status" : "A" }
   { "_id" : 3, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 50, "items" : { "sku" : "pears", "qty" : 10, "price" : 2.5 }, "status" : "A" }
   { "_id" : 4, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-18T00:00:00Z"), "price" : 25, "items" : { "sku" : "oranges", "qty" : 10, "price" : 2.5 }, "status" : "A" }
   { "_id" : 5, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-19T00:00:00Z"), "price" : 50, "items" : { "sku" : "chocolates", "qty" : 5, "price" : 10 }, "status" : "A" }
   ...
   ```
3. `$group`由平台组`items.sku`，计算每个SKU：

   * `qty`字段。该`qty`字段包含`qty`每个订单的总数`items.sku`（请参阅参考资料`$sum`）。
   * `orders_ids`阵列。该`orders_ids`字段包含不同顺序的阵列`_id`的对`items.sku`（参见 `$addToSet`）。

   ```
   { "_id" : "chocolates", "qty" : 15, "orders_ids" : [ 2, 5, 8 ] }
   { "_id" : "oranges", "qty" : 63, "orders_ids" : [ 4, 7, 3, 2, 9, 1, 10 ] }
   { "_id" : "carrots", "qty" : 15, "orders_ids" : [ 6, 9 ] }
   { "_id" : "apples", "qty" : 35, "orders_ids" : [ 9, 8, 1, 6 ] }
   { "_id" : "pears", "qty" : 10, "orders_ids" : [ 3 ] }
   ```
4. `$project`阶段调整输出文档的形状以反映map-reduce的输出，该输出具有两个字段`_id`和 `value`。该`$project`sets：

   * `value.count`的尺寸在`orders_ids`数组中。（请参阅`$size`。）
   * `value.qty`在`qty`输入文档的字段。
   * `value.avg`每订购数量的平均数目。（请参阅`$divide`和`$size`。）

   ```
   { "_id" : "apples", "value" : { "count" : 4, "qty" : 35, "avg" : 8.75 } }
   { "_id" : "pears", "value" : { "count" : 1, "qty" : 10, "avg" : 10 } }
   { "_id" : "chocolates", "value" : { "count" : 3, "qty" : 15, "avg" : 5 } }
   { "_id" : "oranges", "value" : { "count" : 7, "qty" : 63, "avg" : 9 } }
   { "_id" : "carrots", "value" : { "count" : 2, "qty" : 15, "avg" : 7.5 } }
   ```
5. 最后，`$merge`将输出写入collection `agg_alternative_3`。如果现有文档的密钥`_id`与新结果相同，则该操作将覆盖现有文档。如果不存在具有相同密钥的文档，则该操作将插入该文档。
6. 查询`agg_alternative_3`集合以验证结果：

   ```
   db.agg_alternative_3.find().sort( { _id: 1 } )
   ```

   该操作返回以下文档：

   ```
   { "_id" : "apples", "value" : { "count" : 4, "qty" : 35, "avg" : 8.75 } }
   { "_id" : "carrots", "value" : { "count" : 2, "qty" : 15, "avg" : 7.5 } }
   { "_id" : "chocolates", "value" : { "count" : 3, "qty" : 15, "avg" : 5 } }
   { "_id" : "oranges", "value" : { "count" : 7, "qty" : 63, "avg" : 9 } }
   { "_id" : "pears", "value" : { "count" : 1, "qty" : 10, "avg" : 10 } }
   ```

## 输出

db.collection.mapReduce()方法的输出与MapReduce命令的输出相同。有关db.collection.mapReduce()输出的信息，请参阅MapReduce命令的产量部分。

## 限制

MongoDB驱动程序会自动将afterClusterTime设置为与因果一致的会话相关联的操作。从MongoDB 4.2开始， `db.collection.mapReduce()`不再支持 afterClusterTime。因此， `db.collection.mapReduce()`不能与因果一致的会话相关联 。

## 附加信息

* 对 Map Function 进行故障排除
* 排除 Reduce Function 问题
* MapReduce命令
* 聚合
* Map-Reduce
* 执行增量 Map-Reduce

译者：李冠飞

校对：


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.mongoing.com/can-kao/mongo-shell-methods/collection-methods/db-collection-mapreduce.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
