On this page本页内容
Starting in MongoDB 5.0, map-reduce is deprecated:从MongoDB 5.0开始,不推荐使用map-reduce:
$group, $merge, and others.$group、$merge等)重写map-reduce操作。$accumulator and $function aggregation operators, available starting in version 4.4. $accumulator和$function聚合运算符,从4.4版开始提供。For examples of aggregation pipeline alternatives to map-reduce, see:有关映射减少的聚合管道备选方案的示例,请参阅:
mapReduce The mapReduce command allows you to run map-reduce aggregation operations over a collection.mapReduce命令允许您对集合运行map-reduce聚合操作。
Starting in version 4.4, MongoDB ignores the verbose option.从4.4版开始,MongoDB忽略了verbose选项。
Starting in version 4.2, MongoDB deprecates:从4.2版开始,MongoDB不推荐:
sharded选项进行map-reduce。要输出到分片集合,请首先创建分片集合。MongoDB 4.2也不赞成替换现有的分片集合。nonAtomic: false选项的显式规范。The mapReduce command has the following syntax:mapReduce命令具有以下语法:
db.runCommand( {
mapReduce: <string>,
map: <string or JavaScript>,
reduce: <string or JavaScript>,
finalize: <string or JavaScript>,
out: <output>,
query: <document>,
sort: <document>,
limit: <number>,
scope: <document>,
jsMode: <boolean>,
verbose: <boolean>,
bypassDocumentValidation: <boolean>,
collation: <document>,
writeConcern: <document>,
comment: <any>
} )
The command takes the following fields as arguments:该命令将以下字段作为参数:
mapReduce | string |
|
map | JavaScript or String |
|
reduce | JavaScript or String |
|
out | string or document |
|
query | document |
|
sort | document |
|
limit | number |
|
finalize | JavaScript or String |
|
scope | document |
|
jsMode | boolean |
|
verbose | boolean |
|
bypassDocumentValidation | boolean |
|
collation | document |
collation: {
locale: <string>,
caseLevel: <boolean>,
caseFirst: <string>,
strength: <int>,
numericOrdering: <boolean>,
alternate: <string>,
maxVariable: <string>,
backwards: <boolean>
}
|
writeConcern | document |
|
comment | any |
|
The following is a prototype usage of the 以下是mapReduce command:mapReduce命令的原型用法:
var mapFunction = function() { ... }; var reduceFunction = function(key, values) { ... }; db.runCommand( { mapReduce: <input-collection>, map: mapFunction, reduce: reduceFunction, out: { merge: <output-collection> }, query: <query> } )
Although 尽管mapReduce uses JavaScript, most interactions with MongoDB do not use JavaScript but use an idiomatic driver in the language of the interacting application.mapReduce使用JavaScript,但与MongoDB的大多数交互都不使用JavaScript而是使用交互应用程序语言中的惯用驱动程序。
map Functionmap函数要求The map function is responsible for transforming each input document into zero or more documents. map函数负责将每个输入文档转换为零个或多个文档。It can access the variables defined in the 它可以访问scope parameter, and has the following prototype:scope参数中定义的变量,并具有以下原型:
function() { ... emit(key, value); }
The map function has the following requirements:map函数有以下要求:
map function, reference the current document as this within the function.map函数中,在函数中将当前文档引用为this。map function should not access the database for any reason.map函数不应出于任何原因访问数据库。map function should be pure, or have no impact outside of the function (i.e. side effects.)map函数应该是纯函数,或者在函数之外没有影响(即副作用)map function may optionally call emit(key,value) any number of times to create an output document associating key with value.map函数可以可选地调用emit(key,value)任意次数,以创建将key与value关联的输出文档。Starting in MongoDB 4.4, mapReduce no longer supports the deprecated BSON type JavaScript code with scope (BSON type 15) for its functions. The map function must be either BSON type String (BSON type 2) or BSON type JavaScript (BSON type 13). To pass constant values which will be accessible in the map function, use the scope parameter.
map function has been deprecated since version 4.2.1.map函数使用带有scope的JavaScript代码。The following map function will call emit(key,value) either 0 or 1 times depending on the value of the input document's status field:
function() { if (this.status == 'A') emit(this.cust_id, 1); }
The following map function may call emit(key,value) multiple times depending on the number of elements in the input document's items field:
function() { this.items.forEach(function(item){ emit(item.sku, 1); }); }
reduce FunctionThe reduce function has the following prototype:
function(key, values) { ... return result; }
The reduce function exhibits the following behaviors:
reduce function should not access the database, even to perform read operations.reduce function should not affect the outside system.reduce function for a key that has only a single value. The values argument is an array whose elements are the value objects that are "mapped" to the key.reduce function more than once for the same key. In this case, the previous output from the reduce function for that key will become one of the input values to the next reduce function invocation for that key.reduce function can access the variables defined in the scope parameter.reduce must not be larger than half of MongoDB's maximum BSON document size. This requirement may be violated when large documents are returned and then joined together in subsequent reduce steps.Starting in MongoDB 4.4, mapReduce no longer supports the deprecated BSON type JavaScript code with scope (BSON type 15) for its functions. The reduce function must be either BSON type String (BSON type 2) or BSON type JavaScript (BSON type 13). To pass constant values which will be accessible in the reduce function, use the scope parameter.
reduce function has been deprecated since version 4.2.1.Because it is possible to invoke the reduce function more than once for the same key, the following properties need to be true:
value emitted by the map function.the reduce function must be associative. The following statement must be true:
reduce(key, [ C, reduce(key, [ A, B ]) ] ) == reduce( key, [ C, A, B ] )
the reduce function must be idempotent. Ensure that the following statement is true:
reduce( key, [ reduce(key, valuesArray) ] ) == reduce( key, valuesArray )
the reduce function should be commutative: that is, the order of the elements in the valuesArray should not affect the output of the reduce function, so that the following statement is true:
reduce( key, [ A, B ] ) == reduce( key, [ B, A ] )
finalize FunctionThe finalize function has the following prototype:
function(key, reducedValue) { ... return modifiedObject; }
The finalize function receives as its arguments a key value and the reducedValue from the reduce function. Be aware that:
finalize function should not access the database for any reason.finalize function should be pure, or have no impact outside of the function (i.e. side effects.)finalize function can access the variables defined in the scope parameter.Starting in MongoDB 4.4, mapReduce no longer supports the deprecated BSON type JavaScript code with scope (BSON type 15) for its functions. The finalize function must be either BSON type String (BSON type 2) or BSON type JavaScript (BSON type 13). To pass constant values which will be accessible in the finalize function, use the scope parameter.
finalize function has been deprecated since version 4.2.1.outYou can specify the following options for the 可以为out parameter:out参数指定以下选项:
This option outputs to a new collection, and is not available on secondary members of replica sets.此选项输出到新集合,并且在副本集的辅助成员上不可用。
out: <collectionName>
Starting in version 4.2, MongoDB deprecates:从4.2版开始,MongoDB不推荐:
sharded选项进行map-reduce。nonAtomic: false选项的显式规范。This option is only available when passing a collection that already exists to 此选项仅在将已存在的集合传递给out. out时可用。It is not available on secondary members of replica sets.它在副本集的辅助成员上不可用。
out: { <action>: <collectionName>
[, db: <dbName>]
[, sharded: <boolean> ]
[, nonAtomic: <boolean> ] }
When you output to a collection with an action, the 当您使用操作输出到集合时,out has the following parameters:out具有以下参数:
<action>: Specify one of the following actions::指定以下操作之一:
replace
Replace the contents of the 如果具有<collectionName> if the collection with the <collectionName> exists.<collectionName>的集合存在,则替换<collecationName>的内容。
merge
Merge the new result with the existing result if the output collection already exists. 如果输出集合已存在,则将新结果与现有结果合并。If an existing document has the same key as the new result, overwrite that existing document.如果现有文档与新结果具有相同的键,则覆盖该现有文档。
reduce
Merge the new result with the existing result if the output collection already exists. 如果输出集合已存在,请将新结果与现有结果合并。If an existing document has the same key as the new result, apply the 如果现有文档与新结果具有相同的键,请将reduce function to both the new and the existing documents and overwrite the existing document with the result.reduce函数应用于新文档和现有文档,并用结果覆盖现有文档。
db:
Optional. 可选。The name of the database that you want the map-reduce operation to write its output. 希望map-reduce操作写入其输出的数据库的名称。By default this will be the same database as the input collection.默认情况下,这将是与输入集合相同的数据库。
sharded:
Starting in version 4.2, the use of the 从4.2版开始,不推荐使用sharded option is deprecated.sharded选项。
Optional. 可选。If 如果为true and you have enabled sharding on output database, the map-reduce operation will shard the output collection using the _id field as the shard key.true,并且您已经在输出数据库上启用了分片,则map-reduce操作将使用_id字段作为分片键来分片输出集合。
If 如果true and collectionName is an existing unsharded collection, map-reduce fails.true且collectionName是现有的未共享集合,则map-reduce失败。
nonAtomic:
Starting in MongoDB 4.2, explicitly setting 从MongoDB 4.2开始,不推荐将nonAtomic to false is deprecated.nonAtomic显式设置为false。
Optional. 可选。Specify output operation as non-atomic. 将输出操作指定为非原子操作。This applies only to the 这仅适用于merge and reduce output modes, which may take minutes to execute.merge和reduce输出模式,这可能需要几分钟的时间才能执行。
By default nonAtomic is false, and the map-reduce operation locks the database during post-processing.
If nonAtomic is true, the post-processing step prevents MongoDB from locking the database: during this time, other clients will be able to read intermediate states of the output collection.
Perform the map-reduce operation in memory and return the result. 在内存中执行map reduce操作并返回结果。This option is the only available option for 此选项是复制副本集辅助成员上out on secondary members of replica sets.out唯一可用的选项。
out: { inline: 1 }
The result must fit within the maximum size of a BSON document.结果必须符合BSON文档的最大大小。
If your MongoDB deployment enforces authentication, the user executing the 如果MongoDB部署强制身份验证,则执行mapReduce command must possess the following privilege actions:mapReducee命令的用户必须拥有以下权限操作:
Map-reduce with {out : inline} output option:
Map-reduce with the replace action when outputting to a collection:
Map-reduce with the merge or reduce actions when outputting to a collection:
The readWrite built-in role provides the necessary permissions to perform map-reduce aggregation.
MongoDB drivers automatically set afterClusterTime for operations associated with causally consistent sessions. Starting in MongoDB 4.2, the mapReduce command no longer support afterClusterTime. As such, mapReduce cannot be associatd with causally consistent sessions.
In mongosh, the db.collection.mapReduce() method is a wrapper around the mapReduce command. The following examples use the db.collection.mapReduce() method:
The examples in this section include aggregation pipeline alternatives without custom aggregation expressions. For alternatives that use custom expressions, see Map-Reduce to Aggregation Pipeline Translation Examples.
Create a sample collection orders with these documents:
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" }
])
Perform the map-reduce operation on the orders collection to group by the cust_id, and calculate the sum of the price for each cust_id:
Define the map function to process each input document:定义映射函数以处理每个输入文档:
this refers to the document that the map-reduce operation is processing.this引用map-reduce操作正在处理的文档。price to the cust_id for each document and emits the cust_id and price.var mapFunction1 = function() { emit(this.cust_id, this.price); };
Define the corresponding reduce function with two arguments 使用两个参数keyCustId and valuesPrices:keyCustId和valuesPrices定义相应的reduce函数:
valuesPrices is an array whose elements are the price values emitted by the map function and grouped by keyCustId.valuesPrice array to the sum of its elements.var reduceFunction1 = function(keyCustId, valuesPrices) { return Array.sum(valuesPrices); };
Perform map-reduce on all documents in the 使用orders collection using the mapFunction1 map function and the reduceFunction1 reduce function:mapFunction1映射函数和reduceFunction1-reduce函数对orders集合中的所有文档执行映射缩减:
db.orders.mapReduce(
mapFunction1,
reduceFunction1,
{ out: "map_reduce_example" }
)
This operation outputs the results to a collection named 此操作将结果输出到名为map_reduce_example. map_reduce_example的集合。If the 如果map_reduce_example collection already exists, the operation will replace the contents with the results of this map-reduce operation.map_reduce_example集合已经存在,则该操作将用此map-reduce操作的结果替换内容。
Query the map_reduce_example collection to verify the results:
db.map_reduce_example.find().sort( { _id: 1 } )
The operation returns these documents:该操作将返回以下文档:
{ "_id" : "Ant O. Knee", "value" : 95 }
{ "_id" : "Busby Bee", "value" : 125 }
{ "_id" : "Cam Elot", "value" : 60 }
{ "_id" : "Don Quis", "value" : 155 }
Using the available aggregation pipeline operators, you can rewrite the map-reduce operation without defining custom functions:使用可用的聚合管道运算符,您可以在不定义自定义函数的情况下重写map-reduce操作:
db.orders.aggregate([
{ $group: { _id: "$cust_id", value: { $sum: "$price" } } },
{ $out: "agg_alternative_1" }
])
The $group stage groups by the cust_id and calculates the value field (See also $sum). The value field contains the total price for each cust_id.
The stage output the following documents to the next stage:
{ "_id" : "Don Quis", "value" : 155 }
{ "_id" : "Ant O. Knee", "value" : 95 }
{ "_id" : "Cam Elot", "value" : 60 }
{ "_id" : "Busby Bee", "value" : 125 }
$out writes the output to the collection agg_alternative_1. Alternatively, you could use $merge instead of $out.Query the 查询agg_alternative_1 collection to verify the results:agg_alternative_1集合以验证结果:
db.agg_alternative_1.find().sort( { _id: 1 } )
The operation returns the following documents:该操作将返回以下文档:
{ "_id" : "Ant O. Knee", "value" : 95 }
{ "_id" : "Busby Bee", "value" : 125 }
{ "_id" : "Cam Elot", "value" : 60 }
{ "_id" : "Don Quis", "value" : 155 }
For an alternative that uses custom aggregation expressions, see Map-Reduce to Aggregation Pipeline Translation Examples.有关使用自定义聚合表达式的备选方案,请参阅Map-Reduce到聚合管道转换示例。
In the following example, you will see a map-reduce operation on the 在下面的示例中,您将看到orders collection for all documents that have an ord_date value greater than or equal to 2020-03-01.ord_date值大于或等于2020-03-01的所有文档的orders集合上的map-reduce操作。
The operation in the example:示例中的操作:
item.sku field, and calculates the number of orders and the total quantity ordered for each sku.item.sku字段分组,并计算每个sku的订单数量和总订单数量。sku value and merges the results into the output collection.sku值的每个订单的平均数量,并将结果合并到输出集合中。When merging results, if an existing document has the same key as the new result, the operation overwrites the existing document. 合并结果时,如果现有文档与新结果具有相同的键,则该操作将覆盖现有文档。If there is no existing document with the same key, the operation inserts the document.如果没有具有相同键的现有文档,则该操作将插入该文档。
Example steps:
Define the map function to process each input document:定义映射函数以处理每个输入文档:
this refers to the document that the map-reduce operation is processing.this是指map reduce操作正在处理的文档。sku with a new object value that contains the count of 1 and the item qty for the order and emits the sku (stored in the key) and the 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); } };
Define the corresponding reduce function with two arguments 使用两个参数keySKU and countObjVals:keySKU和countObjVals定义相应的reduce函数:
countObjValskeySKU values passed by map function to the reducer function.keySKU值的对象。countObjVals array to a single object reducedValue that contains the count and the qty fields.reducedVal, the count field contains the sum of the count fields from the individual array elements, and the qty field contains the sum of the qty fields from the individual array elements.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; };
Define a finalize function with two arguments 定义一个带有两个参数key and reducedVal. key和reducedVal的finalize函数。The function modifies the 该函数修改reducedVal object to add a computed field named avg and returns the modified object:reducedVal对象以添加名为avg的计算字段,并返回修改后的对象:
var finalizeFunction2 = function (key, reducedVal) { reducedVal.avg = reducedVal.qty/reducedVal.count; return reducedVal; };
Perform the map-reduce operation on the 使用orders collection using the mapFunction2, reduceFunction2, and finalizeFunction2 functions:mapFunction2、reduceFunction3和finalizeFunction4函数对orders集合执行map-reduce操作:
db.orders.mapReduce(
mapFunction2,
reduceFunction2,
{
out: { merge: "map_reduce_example2" },
query: { ord_date: { $gte: new Date("2020-03-01") } },
finalize: finalizeFunction2
}
);
This operation uses the query field to select only those documents with ord_date greater than or equal to new Date("2020-03-01"). Then it outputs the results to a collection map_reduce_example2.
If the 如果map_reduce_example2 collection already exists, the operation will merge the existing contents with the results of this map-reduce operation. map_reduce_example2集合已经存在,则该操作将将现有内容与此map-reduce操作的结果合并。That is, if an existing document has the same key as the new result, the operation overwrites the existing document. 也就是说,如果现有文档具有与新结果相同的键,则该操作将覆盖现有文档。If there is no existing document with the same key, the operation inserts the document.如果没有具有相同键的现有文档,则该操作将插入该文档。
Query the 查询map_reduce_example2 collection to verify the results:map_reduce_example2集合以验证结果:
db.map_reduce_example2.find().sort( { _id: 1 } )
The operation returns these documents:该操作将返回以下文档:
{ "_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 } }
Using the available aggregation pipeline operators, you can rewrite the map-reduce operation without defining custom functions:使用可用的聚合管道运算符,您可以在不定义自定义函数的情况下重写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" } }
] )
$match stage selects only those documents with ord_date greater than or equal to new Date("2020-03-01").$match阶段仅选择ord_date大于或等于new Date("2020-03-01")的文档。The $unwind stage breaks down the document by the items array field to output a document for each array element. $unwind阶段通过items数组字段分解文档,为每个数组元素输出一个文档。For Example:例如:
{ "_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" }
...
The $group stage groups by the items.sku, calculating for each sku:
qty field. The qty field contains theqty ordered per each items.sku (See $sum).orders_ids array. The orders_ids field contains an_id's for the items.sku (See $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 ] }
$project stage reshapes the output document to mirror the map-reduce's output to have two fields _id and value. The $project sets:The $unwind stage breaks down the document by the items array field to output a document for each array element. For Example:例如:
{ "_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" }
...
The $group stage groups by the items.sku, calculating for each sku:
qty field. The qty field contains the total qty ordered per each items.sku using $sum.orders_ids array. The orders_ids field contains an array of distinct order _id's for the items.sku using $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 ] }
The $project stage reshapes the output document to mirror the map-reduce's output to have two fields _id and value. The $project sets:
value.count to the size of the orders_ids array using $size.value.qty to the qty field of input document.value.avg to the average number of qty per order using $divide and $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 } }
$merge writes the output to the collection agg_alternative_3. $merge将输出写入集合agg_alternative_3。_id as the new result, the operation overwrites the existing document. _id,则该操作将覆盖现有文档。Query the 查询agg_alternative_3 collection to verify the results:agg_alternative_3集合以验证结果:
db.agg_alternative_3.find().sort( { _id: 1 } )
The operation returns the following documents:该操作将返回以下文档:
{ "_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 } }
For an alternative that uses custom aggregation expressions, see Map-Reduce to Aggregation Pipeline Translation Examples.有关使用自定义聚合表达式的备选方案,请参阅将Reduce映射到聚合管道转换示例。
For more information and examples, see the Map-Reduce page and Perform Incremental Map-Reduce.有关更多信息和示例,请参阅Map—Reduce页面和执行增量Map—Reduce。
If you set the out parameter to write the results to a collection, the 如果设置out参数以将结果写入集合,mapReduce command returns a document in the following form:mapReduce命令将返回以下格式的文档:
{ "result" : "map_reduce_example", "ok" : 1 }{
"result" : <string or document>,
"timeMillis" : <int>,
"counts" : {
"input" : <int>,
"emit" : <int>,
"reduce" : <int>,
"output" : <int>
},
"ok" : <int>,
}If you set the out parameter to output the results inline, the mapReduce command returns a document in the following form:
{
"results" : [
{
"_id" : <key>,
"value" :<reduced or finalizedValue for key>
},
...
],
"ok" : <int>
}{
"results" : [
{
"_id" : <key>,
"value" :<reduced or finalizedValue for key>
},
...
],
"timeMillis" : <int>,
"counts" : {
"input" : <int>,
"emit" : <int>,
"reduce" : <int>,
"output" : <int>
},
"ok" : <int>
}mapReduce.results For output written inline, an array of resulting documents. 对于内联写入的输出,生成的文档数组。Each resulting document contains two fields:每个结果文档包含两个字段:
_idkey value,key值,valuekey.key的缩减或最终值。mapReduce.timeMillis Available for MongoDB 4.2 and earlier only仅适用于MongoDB 4.2及更早版本
The command execution time in milliseconds.命令执行时间(毫秒)。
mapReduce.counts Available for MongoDB 4.2 and earlier only仅适用于MongoDB 4.2及更早版本
Various count statistics from the mapReduce command.mapReduce命令中的各种计数统计信息。
mapReduce.counts.input Available for MongoDB 4.2 and earlier only仅适用于MongoDB 4.2及更早版本
The number of input documents, which is the number of times the 输入文档数,即mapReduce command called the map function.mapReduce命令调用map函数的次数。
mapReduce.counts.emit Available for MongoDB 4.2 and earlier only仅适用于MongoDB 4.2及更早版本
The number of times the mapReduce command called the emit function.mapReduce命令调用emit函数的次数。
mapReduce.counts.reduce Available for MongoDB 4.2 and earlier only仅适用于MongoDB 4.2及更早版本
The number of times the mapReduce command called the reduce function.mapReduce命令调用reduce函数的次数。
mapReduce.counts.output Available for MongoDB 4.2 and earlier only仅适用于MongoDB 4.2及更早版本
The number of output values produced.生成的输出值的数量。
mapReduce.ok A value of 值为1 indicates the mapReduce command ran successfully. 1表示mapReduce命令已成功运行。A value of 值为0 indicates an error.0表示错误。
In addition to the aforementioned command specific return fields, the db.runCommand() includes additional information:
$clusterTime, and operationTime.operationTime and $clusterTime.See db.runCommand Response for details on these fields.