MapReduce
注意
作为 Map-Reduce 替代方案的聚合管道
从MongoDB 5.0开始, map-reduce已弃用:
您应该使用聚合管道,而不是 map-reduce。聚合管道提供比 map-reduce 更好的性能和可用性。
对于需要自定义功能的 map-reduce 操作,可以使用
$accumulator
和$function
聚合操作符。可以使用这些操作符在 JavaScript 中定义自定义聚合表达式。
有关 map-reduce 的聚合管道替代方案的示例,请参阅:
定义
mapReduce
mapReduce
命令允许您对集合运行map-reduce聚合操作。提示
在
mongosh
中,该命令也可通过mapReduce()
辅助方法运行。辅助方法对
mongosh
用户来说很方便,但它们返回的信息级别可能与数据库命令不同。如果不追求方便或需要额外的返回字段,请使用数据库命令。
兼容性
此命令可用于以下环境中托管的部署:
MongoDB Atlas:用于云中 MongoDB 部署的完全托管服务
重要
M 0 、M 2和 M 5集群不支持此命令。 有关更多信息,请参阅不支持的命令。
MongoDB Enterprise:基于订阅、自我管理的 MongoDB 版本
MongoDB Community:源代码可用、免费使用且可自行管理的 MongoDB 版本
语法
注意
该命令具有以下语法:
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>, maxTimeMS: <integer>, writeConcern: <document>, comment: <any> } )
命令字段
命令将以下字段作为参数:
字段 | 类型 | 说明 | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
字符串 | 要对其执行 map-reduce 的集合的名称。此集合在由 视图不支持 map-reduce 操作。 | |||||||||||
JavaScript 或字符串 | 一个 JavaScript 函数,用于将 更多信息,请参阅对 map 函数的要求。 | |||||||||||
JavaScript 或字符串 | 一个 JavaScript 函数,可将与特定 有关更多信息,请参阅 reduce 函数的要求。 | |||||||||||
字符串或文档 | ||||||||||||
文档 | 可选。使用查询运算符指定选择标准,确定输入到 | |||||||||||
文档 | 可选。对输入文档排序。此选项对于优化非常有用。例如,将排序键指定为与发出键相同,这样可减少 reduce 操作。排序键必须位于此集合的现有索引中。 | |||||||||||
数字 | 可选。指定输入到 | |||||||||||
JavaScript 或字符串 | 可选。一个 JavaScript 函数,用于修改 更多信息,请参阅对 finalize 函数的要求。 | |||||||||||
文档 | 可选。指定可在 | |||||||||||
布尔 | 可选。指定是否在计算 默认值为 如果为
如果为
| |||||||||||
布尔 | ||||||||||||
布尔 | ||||||||||||
文档 | 可选。 指定用于操作的排序规则。 排序规则允许用户为字符串比较指定特定于语言的规则,例如字母大小写和重音符号规则。 排序规则选项的语法如下:
指定排序规则时, 如果未指定排序规则,但集合具有默认排序规则(请参阅 如果没有为收集或操作指定排序规则,MongoDB 将使用先前版本中使用的简单二进制比较来进行字符串比较。 您不能为一个操作指定多个排序规则。例如,您不能为每个字段指定不同的排序规则,或者如果执行带排序的查找,则不能使用一种排序规则进行查找而另一种排序规则进行排序。 | |||||||||||
maxTimeMS | non-negative integer | 可选。 指定时间限制(以毫秒为单位)。如果您未指定 MongoDB 使用与 | ||||||||||
文档 | 可选。一种文档,表示输出到集合时要使用的写关注。省略以使用默认的写关注。 | |||||||||||
comment | any | 可选。用户提供的待附加到该命令的注释。设置后,该注释将与该命令的记录一起出现在以下位置:
注释可以是任何有效的 BSON 类型(字符串、整型、对象、数组等)。 |
使用
下面是 mapReduce
命令的原型用法:
var mapFunction = function() { ... }; var reduceFunction = function(key, values) { ... }; db.runCommand( { mapReduce: <input-collection>, map: mapFunction, reduce: reduceFunction, out: { merge: <output-collection> }, query: <query> } )
注意
MongoDB 中的 JavaScript
map
函数的要求
map
函数负责将每个输入文档转换为零个或多个文档。它可以访问 scope
参数中定义的变量,并具有以下原型:
function() { ... emit(key, value); }
map
函数具有以下要求:
在
map
函数中,将当前文档引用为函数内的this
。map
函数不应 出于任何原因访问数据库。map
函数应该是纯函数,或者对函数外部没有影响(即副作用)。map
函数可以选择调用emit(key,value)
任意次,以创建将key
与value
关联的输出文档。
以下 map
函数将调用 emit(key,value)
0 次或 1 次,具体取决于输入文档的 status
字段的值:
function() { if (this.status == 'A') emit(this.cust_id, 1); }
以下 map
函数可能会多次调用 emit(key,value)
,具体取决于输入文档的 items
字段中的元素数量:
function() { this.items.forEach(function(item){ emit(item.sku, 1); }); }
reduce
函数的要求
reduce
函数具有以下原型:
function(key, values) { ... return result; }
reduce
函数表现出以下行为:
reduce
函数不应访问数据库,即使是执行读操作也是如此。reduce
函数不应 影响外部系统。MongoDB 可以针对同一键多次调用
reduce
函数。在这种情况下,该键的reduce
函数的先前输出将成为该键的下一个reduce
函数调用的输入值之一。reduce
函数可以访问scope
参数中定义的变量。reduce
的输入不得大于 MongoDB 最大 BSON 文档大小的一半。当返回大型文档并在后续的reduce
步骤中将其连接在一起时,可能会违反此要求。
由于可以针对同一键多次调用 reduce
函数,因此以下属性必须为 true:
返回对象的类型必须与
map
函数发出的value
的类型相同。reduce
函数必须是关联函数。以下语句必须为 true:reduce(key, [ C, reduce(key, [ A, B ]) ] ) == reduce( key, [ C, A, B ] ) reduce
函数必须是幂等的。确保以下语句为 true:reduce( key, [ reduce(key, valuesArray) ] ) == reduce( key, valuesArray ) reduce
函数应该是可交换的:也就是说,valuesArray
中元素的顺序不应影响reduce
函数的输出,因此以下语句成立:reduce( key, [ A, B ] ) == reduce( key, [ B, A ] )
finalize
函数的要求
finalize
函数具有以下原型:
function(key, reducedValue) { ... return modifiedObject; }
finalize
函数接收 key
值和来自 reduce
函数的 reducedValue
作为其参数。请注意:
finalize
函数不应 出于任何原因访问数据库。finalize
函数应该是纯函数,或者对函数外部没有影响(即副作用)。finalize
函数可以访问scope
参数中定义的变量。
out
选项
您可以为 out
参数指定以下选项:
输出到集合
此选项输出到新集合,并且在副本集的从节点上不可用。
out: <collectionName>
输出到具有操作的集合
注意
从版本 4.2 开始,MongoDB 弃用了:
用于创建新的分片集合的 map-reduce 选项,以及对 map-reduce 使用分片选项。要输出到分片集合,请首先创建分片集合。MongoDB 4.2 还弃用了替换现有分片集合的功能。
仅当将已存在的集合传递给 out
时,此选项才可用。它不适用于副本集的从节点。
out: { <action>: <collectionName> [, db: <dbName>] [, sharded: <boolean> ] }
当使用操作输出到集合时,out
具有以下参数:
<action>
:指定以下操作之一:replace
如果存在具有
<collectionName>
的集合,则替换<collectionName>
的内容。merge
如果输出集合已经存在,则将新结果与现有结果合并。如果现有文档与新结果具有相同的键,则覆盖该现有文档。
reduce
如果输出集合已经存在,则将新结果与现有结果合并。如果现有文档与新结果具有相同的键,请将
reduce
函数应用于新文档和现有文档,并使用结果覆盖现有文档。
db
:可选。您希望 map-Reduce 操作写入其输出的数据库的名称。默认情况下,这将是与输入集合相同的数据库。
输出内联
在内存中执行 map-reduce 操作并返回结果。此选项是副本集的从节点上 out
的唯一可用选项。
out: { inline: 1 }
结果必须符合 BSON 文档的最大大小。
必需的访问权限
如果您的 MongoDB 部署强制进行身份验证,则执行 mapReduce
命令的用户必须拥有以下权限操作:
带有 {out : inline}
输出选项的 map-reduce:
输出到集合时使用 replace
操作执行 Map-reduce:
输出到集合时使用 merge
或 reduce
操作执行 Map-reduce:
readWrite
内置角色为执行 map-reduce 聚合提供了必要的权限。
限制
mapReduce
命令不再支持 afterClusterTime。因此,mapReduce
不能与因果一致的会话相关联。
Map-Reduce 示例
在 mongosh
中,db.collection.mapReduce()
方法是 mapReduce
命令的封装器。以下示例使用 db.collection.mapReduce()
方法:
本节中的示例包括不带自定义聚合表达式的聚合管道替代方案。有关使用自定义表达式的替代方案,请参阅Map-Reduce 到聚合管道转换示例。
创建一个包含以下文档的样本集合 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" } ])
返回每位客户的总价
针对 orders
集合执行 map-reduce 操作会按 cust_id
进行分组,并为每个 cust_id
计算 price
之和:
定义 Map 函数来处理每个输入文档:
在函数中,
this
指的是 Map-Reduce 操作正在处理的文档。该函数将每个文档的
price
映射到cust_id
,并输出cust_id
和price
。
var mapFunction1 = function() { emit(this.cust_id, this.price); }; 使用两个参数
keyCustId
和valuesPrices
定义相应的 Reduce 函数:valuesPrices
是一个数组,其元素是由 Map 函数发出并按keyCustId
分组的price
值。该函数将
valuesPrice
数组缩减为其元素之和。
var reduceFunction1 = function(keyCustId, valuesPrices) { return Array.sum(valuesPrices); }; 使用
mapFunction1
Map 函数和reduceFunction1
Reduce 函数对orders
集合中的所有文档执行 Map-Reduce:db.orders.mapReduce( mapFunction1, reduceFunction1, { out: "map_reduce_example" } ) 此操作将结果输出到名为
map_reduce_example
的集合。如果map_reduce_example
集合已存在,该操作将用此 Map-Reduce 操作的结果替换其内容。查询
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" } ])
$group
阶段按cust_id
分组并计算value
字段(另见$sum
)。value
字段包含每个cust_id
的price
总额。此阶段将以下文档输出到下一阶段:
{ "_id" : "Don Quis", "value" : 155 } { "_id" : "Ant O. Knee", "value" : 95 } { "_id" : "Cam Elot", "value" : 60 } { "_id" : "Busby Bee", "value" : 125 } 查询
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 }
通过每款商品的平均数量计算订单和总数量
在以下示例中,您将看到针对 ord_date
值大于或等于 2020-03-01
的所有文档对 orders
集合执行的 Map-Reduce 操作。
示例中的操作:
按
item.sku
字段分组,计算每个sku
的订单数量和总订购量。计算每个
sku
值的每个订单的平均数量,并将结果合并到输出集合中。
合并结果时,如果现有文档与新结果具有相同的键,则该操作将覆盖现有文档。如果没有具有相同键的现有文档,操作将插入该文档。
步骤示例:
定义 Map 函数来处理每个输入文档:
在函数中,
this
指的是 Map-Reduce 操作正在处理的文档。对于每款商品,该函数将
sku
与新对象value
关联,该对象包含1
的count
和订单的商品qty
,并发出sku
(存储在key
中)和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); } }; 使用两个参数
keySKU
和countObjVals
定义相应的 Reduce 函数:countObjVals
是一个数组,其元素是映射到分组keySKU
值的对象,这些值由 Map 函数传递到 Reducer 函数。该函数将
countObjVals
数组缩减为包含count
和qty
字段的单个对象reducedValue
。在
reducedVal
中,count
字段包含各个数组元素中count
字段的总和,而qty
字段包含各个数组元素中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; }; 使用两个参数
key
和reducedVal
定义 finalize 函数。该函数会修改reducedVal
对象以添加名为avg
的计算字段并返回修改后的对象:var finalizeFunction2 = function (key, reducedVal) { reducedVal.avg = reducedVal.qty/reducedVal.count; return reducedVal; }; 使用
mapFunction2
、reduceFunction2
和finalizeFunction2
函数对orders
集合执行 Map-Reduce 操作:db.orders.mapReduce( mapFunction2, reduceFunction2, { out: { merge: "map_reduce_example2" }, query: { ord_date: { $gte: new Date("2020-03-01") } }, finalize: finalizeFunction2 } ); 此操作使用
query
字段来仅选择ord_date
大于或等于new Date("2020-03-01")
的文档。然后它将结果输出到集合map_reduce_example2
。如果
map_reduce_example2
集合已存在,该操作会将现有内容与此 Map-Reduce 操作的结果合并。即,如果现有文档的键与新结果相同,则操作会覆盖现有文档。如果没有具有相同键的现有文档,操作将插入该文档。查询
map_reduce_example2
集合以验证结果:db.map_reduce_example2.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 } }
聚合替代方案
利用可用的聚合管道操作符,您可以重写 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
阶段仅选择ord_date
大于等于new Date("2020-03-01")
的文档。$unwind
阶段按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" } ... $group
阶段按items.sku
分组,针对每个 sku 进行计算:qty
字段。qty
字段包含- 每个
items.sku
的订购qty
总计(参见$sum
)。
orders_ids
数组。orders_ids
字段包含一个items.sku
的不同顺序_id
的数组(参见$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
阶段会重塑输出文档以镜像 Map-Reduce 的输出,使其具有两个字段_id
和value
。$project
会:$unwind
阶段按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" } ... $group
阶段按items.sku
分组,针对每个 sku 进行计算:qty
字段。qty
字段包含使用$sum
为每个items.sku
订购的qty
总计。orders_ids
数组。orders_ids
字段包含使用$addToSet
的items.sku
的不同顺序_id
的数组。
{ "_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
阶段会重塑输出文档以镜像 Map-Reduce 的输出,使其具有两个字段_id
和value
。$project
会:使用
$size
将value.count
设置为orders_ids
数组的大小将
value.qty
设置为输入文档中的qty
字段。
{ "_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
将输出写入集合agg_alternative_3
。如果现有文档的键_id
与新结果相同,则操作会覆盖现有文档。如果没有具有相同键的现有文档,操作将插入该文档。查询
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 } }
有关更多信息和示例,请参阅 Map-Reduce 页面和执行增量 Map-Reduce
输出
如果将 out 参数设置为将结果写入集合,mapReduce
命令将以如下形式返回文档:
{ "result" : "map_reduce_example", "ok" : 1 }
如果将 out 参数设置为以内联方式输出结果,mapReduce
命令将返回以下格式的文档:
{ "results" : [ { "_id" : <key>, "value" :<reduced or finalizedValue for key> }, ... ], "ok" : <int> }
mapReduce.ok
值为
1
表示mapReduce
命令运行成功。值为0
表示出现错误。
除了上述特定的命令返回字段外,db.runCommand()
还包括其他信息:
对于副本集:
$clusterTime
和operationTime
。对于分片集群:
operationTime
和$clusterTime
。
有关这些字段的详细信息,请参阅 db.runCommand Response。