On this page
db.collection.mapReduce()
在本页面
db.collection.mapReduce(* map , reduce ,{* , ** , ** , ** , ** , ** , ** , *} *)- db.collection.mapReduce()方法提供了围绕mapReduce命令的包装。
Note
Views不支持 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()采用以下参数:
| Parameter | Type | Description |
|---|---|---|
map |
function | 一个将value与key关联或“Map”并发出key和值pair的 JavaScript 函数。 |
有关更多信息,请参见Map 功能要求。
| reduce | function | JavaScript 函数,将与特定key关联的所有values“减少”到单个对象。
有关更多信息,请参见化简功能的要求。
| options | document |一个文档,它指定db.collection.mapReduce()的附加参数。
| bypassDocumentValidation |布尔值|可选。使mapReduce在操作过程中绕过文档验证。这使您可以插入不符合验证要求的文档。
版本 3.2 中的新功能。
下表描述了db.collection.mapReduce()可以接受的其他参数。
| Field | Type | Description |
|---|---|---|
out |
字符串或文件 | 指定 Map 归约运算结果的位置。您可以输出到集合,使用操作输出到集合或内联输出。对集合的主要成员执行 map-reduce 操作时,您可以输出到集合。在secondary个成员上,您只能使用inline输出。 |
有关更多信息,请参见out Options。
| query | document |使用query operators指定选择标准,以确定 Importing 到map功能的文档。
| sort | document |对* input *文档进行排序。此选项对于优化很有用。例如,将排序键指定为与运行键相同,以便减少还原操作。排序键必须在此集合的现有索引中。
| limit |数字|指定用于 Importingmap函数的最大文档数。
| finalize |功能|可选。遵循reduce方法并修改输出。
有关更多信息,请参见完成功能的要求。
| scope | document |指定可在map,reduce和finalize函数中访问的全局变量。
| jsMode |布尔值|指定在执行map和reduce函数之间是否将中间数据转换为 BSON 格式。
默认为false。
如果false:
在内部,MongoDB 将map函数发出的 JavaScript 对象转换为 BSON 对象。然后,在调用reduce函数时,这些 BSON 对象将转换回 JavaScript 对象。
Map 减少操作将中间 BSON 对象放置在磁盘上的临时存储中。这允许 map-reduce 操作在任意大的数据集上执行。
如果true:
在内部,在map函数期间发出的 JavaScript 对象保留为 JavaScript 对象。无需为reduce函数转换对象,这可以加快执行速度。
您只能对 Map 器的emit()函数使用少于 500,000 个不同的key参数的结果集使用jsMode。
| verbose |布尔值|指定结果信息中是否包含timing信息。将verbose设置为true以包含timing信息。
默认为false。
| collation |文档|可选。
指定用于操作的collation。
Collation允许用户为字符串比较指定特定于语言的规则,例如字母大写和重音符号的规则。
排序规则选项具有以下语法:
collation: {
locale: <string>,
caseLevel: <boolean>,
caseFirst: <string>,
strength: <int>,
numericOrdering: <boolean>,
alternate: <string>,
maxVariable: <string>,
backwards: <boolean>
}
指定排序规则时,locale字段为必填字段;所有其他排序规则字段都是可选的。有关字段的说明,请参见Collation Document。
如果未指定排序规则,但是集合具有默认排序规则(请参见db.createCollection()),则该操作将使用为集合指定的排序规则。
如果没有为集合或操作指定排序规则,则 MongoDB 使用先前版本中使用的简单二进制比较进行字符串比较。
您不能为一个操作指定多个排序规则。例如,您不能为每个字段指定不同的排序规则,或者如果对排序执行查找,则不能对查找使用一种排序规则,而对排序使用另一种排序规则。
3.4 版中的新功能。
Note
map-reduce operations,group命令和$where运算符表达式**无法访问mongoShell 程序中可用的某些全局函数或属性,例如db。
下列 JavaScript 函数和属性**可用于map-reduce operations,group命令和$where运算符表达式:
| Available Properties | Available Functions | |
|---|---|---|
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函数负责将每个 Importing 文档转换为零个或多个文档。它可以访问scope参数中定义的变量,并具有以下原型:
function() {
...
emit(key, value);
}
map函数具有以下要求:
在
map函数中,在函数中以this引用当前文档。map函数不应出于任何原因不能访问数据库。map函数应该是纯函数,或者对函数外部没有任何影响(即副作用)。一次运行只能容纳 MongoDB BSON 文档的最大大小的一半。
map函数可以选择调用emit(key,value)任意次,以创建将key与value关联的输出文档。
以下map函数将根据 Importing 文档的status字段的值调用emit(key,value) 0 或 1 次:
function() {
if (this.status == 'A')
emit(this.cust_id, 1);
}
以下map函数可能会多次调用emit(key,value),具体取决于 Importing 文档的items字段中的元素数量:
function() {
this.items.forEach(function(item){ emit(item.sku, 1); });
}
reduce 函数的要求
reduce函数具有以下原型:
function(key, values) {
...
return result;
}
reduce函数具有以下行为:
reduce函数不应即使也不能执行读取操作。reduce函数应该不影响外部系统。MongoDB 将“不”调用仅具有单个值的键的
reduce函数。values参数是一个数组,其元素是“Map”到key的value对象。MongoDB 可以为同一键多次调用
reduce函数。在这种情况下,该键的reduce函数的先前输出将成为该键的下一个reduce函数调用的 Importing 值之一。reduce函数可以访问scope参数中定义的变量。reduce的 Importing 不得大于 MongoDB BSON 文档的最大大小的一半。当返回大文档然后在随后的reduce步骤中将它们合并在一起时,可能会违反此要求。
因为可以为同一键多次调用reduce函数,所以以下属性必须为 true:
返回对象的* type *必须与
map函数发出的value的类型相同。reduce函数必须是* associative *。以下 Statements 必须为真:
reduce(key, [ C, reduce(key, [ A, B ]) ] ) == reduce( key, [ C, A, B ] )
reduce函数必须是幂等。确保以下语句为真:
reduce( key, [ reduce(key, valuesArray) ] ) == reduce( key, valuesArray )
reduce函数应该是“可交换的”:即valuesArray中元素的 Sequences 不应影响reduce函数的输出,因此以下语句为真:
reduce( key, [ A, B ] ) == reduce( key, [ B, A ] )
out Options
您可以为out参数指定以下选项:
输出到集合
此选项输出到新集合,在副本集的辅助成员上不可用。
out: <collectionName>
通过操作输出到集合
仅当将已经存在的集合传递给out时,此选项才可用。在副本集的辅助成员上不可用。
out: { <action>: <collectionName>
[, db: <dbName>]
[, sharded: <boolean> ]
[, nonAtomic: <boolean> ] }
当您通过操作输出到集合时,out具有以下参数:
<action>:指定以下操作之一:replace
如果存在带有<collectionName>的集合,请替换<collectionName>的内容。
merge
如果输出集合已经存在,则将新结果与现有结果合并。如果现有文档的密钥与新结果相同,则“覆盖”该现有文档。
reduce
如果输出集合已经存在,则将新结果与现有结果合并。如果现有文档的键与新结果相同,则对新文档和现有文档都应用reduce函数,并用结果覆盖现有文档。
db:
可选的。您希望 map-reduce 操作写入其输出的数据库的名称。默认情况下,该数据库将与 Importing 集合相同。
sharded:
可选的。如果true 并且已在输出数据库上启用分片,则 map-reduce 操作将使用_id字段作为分片键对输出集合进行分片。
如果true和collectionName是现有的未分片集合,则 map-reduce 失败。
nonAtomic:
可选的。将输出操作指定为非原子操作。这仅适用于merge和reduce输出模式,这可能需要几分钟才能执行。
默认情况下,nonAtomic为false,并且 map-reduce 操作在后处理期间锁定数据库。
如果nonAtomic为true,则后处理步骤将阻止 MongoDB 锁定数据库:在此期间,其他 Client 端将能够读取输出集合的中间状态。
Output Inline
在内存中执行 map-reduce 操作并返回结果。此选项是副本集的辅助成员上out的唯一可用选项。
out: { inline: 1 }
结果必须符合BSON 文档的最大尺寸。
完成函数的要求
finalize函数具有以下原型:
function(key, reducedValue) {
...
return modifiedObject;
}
finalize函数从reduce函数接收key值和reducedValue作为其参数。意识到:
finalize函数不应出于任何原因不能访问数据库。finalize函数应该是纯函数,或者对函数外部没有任何影响(即副作用)。finalize函数可以访问scope参数中定义的变量。
Map-Reduce Examples
请考虑对包含以下原型文档的集合orders进行以下 map-reduce 操作:
{
_id: ObjectId("50a8240b927d5d8b5891743c"),
cust_id: "abc123",
ord_date: new Date("Oct 04, 2012"),
status: 'A',
price: 25,
items: [ { sku: "mmm", qty: 5, price: 2.5 },
{ sku: "nnn", qty: 5, price: 2.5 } ]
}
返回每个 Client 的总价
对orders集合执行 map-reduce 操作以对cust_id进行分组,并为每个cust_id计算price的总和:
定义 Map 功能来处理每个 Importing 文档:
在函数中,
this表示正在执行 map-reduce 操作的文档。该函数将每个文档的
priceMap 到cust_id并发出cust_id和price对。
var mapFunction1 = function() {
emit(this.cust_id, this.price);
};
使用两个参数
keyCustId和valuesPrices定义相应的 reduce 函数:valuesPrices是一个数组,其元素是 map 函数发出的price值,并按keyCustId分组。该函数将
valuesPrice数组减少为其元素的总和。
var reduceFunction1 = function(keyCustId, valuesPrices) {
return Array.sum(valuesPrices);
};
- 使用
mapFunction1map 函数和reduceFunction1reduce 函数对orders集合中的所有文档执行 map-reduce。
db.orders.mapReduce(
mapFunction1,
reduceFunction1,
{ out: "map_reduce_example" }
)
此操作将结果输出到名为map_reduce_example的集合。如果map_reduce_example集合已经存在,则该操作将使用此 map-reduce 操作的结果替换内容:
计算订单和总数量以及每件商品的平均数量
在此示例中,您将对orders集合上所有ord_date值大于01/01/2012的文档执行 map-reduce 操作。工序按item.sku字段分组,并计算每个sku的订单数量和总 Order 量。通过计算每个sku值的每个订单的平均数量来结束该操作:
定义 Map 功能来处理每个 Importing 文档:
在函数中,
this表示正在执行 map-reduce 操作的文档。对于每个项目,该函数将
sku与新对象value关联,该对象包含1的count和订单的项目qty并发出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);
}
};
使用两个参数
keySKU和countObjVals定义相应的 reduce 函数:countObjVals是一个数组,其元素是 Map 到由 map 函数传递给 reducer 函数的分组的keySKU值的对象。该函数将
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_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 操作的结果合并。
Output
db.collection.mapReduce()方法的输出与mapReduce命令的输出相同。有关db.collection.mapReduce()输出的信息,请参见mapReduce命令的Output部分。