MongoDB-CN-Manual
  • MongoDB中文手册|官方文档中文版
  • MongoDB用户手册说明
  • MongoDB简介
    • 入门
    • 数据库和集合
      • 视图
      • 按需物化视图
      • 封顶集合
      • 时间序列集合
    • 文档
    • BSON类型
      • Comparison and Sort Order
      • MongoDB Extended JSON (v2)
      • MongoDB Extended JSON (v1)
  • 安装 MongoDB
    • 安装MongoDB社区版
      • 在Linux上安装MongoDB社区版
      • 在macOS上安装MongoDB社区版
      • 在Windows上安装MongoDB社区版
    • 安装MongoDB企业版
      • 在Linux上安装MongoDB企业版
      • 在Mac OS安装MongoDB企业版
      • 在Windows安装MongoDB企业版
      • 使用Docker安装MongoDB企业版
    • 将社区版MongoDB升级到企业版MongoDB
    • 验证MongoDB软件包的完整性
  • The mongo Shell
    • 配置mongo Shell
    • 使用 mongo Shell帮助
    • 为mongo Shell编写脚本
    • mongo Shell中的数据类型
    • mongo Shell 快速参考
  • MongoDB CRUD操作
    • 插入文档
      • 插入方法
    • 查询文档
      • 在mongo Shell中迭代游标
      • 从查询返回的项目字段
      • 查询嵌入式文档数组
      • 查询数组
      • 查询空字段或缺少字段
      • 查询嵌入/嵌套文档
    • 更新文档
      • 更新方法
      • 聚合管道更新
    • 删除文档
      • 删除方法
    • 地理空间查询
      • 用地理空间查询查找餐馆
      • GeoJSON对象
    • 批量写入操作
    • 可重试写入
    • 可重试读取
    • SQL到MongoDB的映射图表
    • 文本搜索
      • 文本索引
      • 文本索引操作
      • 集合管道中的文本索引
      • 文本索引语言
    • Read Concern读关注
      • 读关注 "local"
      • 读关注 "available"
      • 读关注 "majority"
      • 读关注 "linearizable"
      • 读关注 "snapshot"
    • Write Concern写关注
    • MongoDB CRUD概念
      • 原子性和事务
      • 读隔离性,一致性和近因性
        • 因果一致性和读写关注
      • 分布式查询
      • 通过findAndModify进行线性化读取
      • 查询计划
      • 查询优化
        • 评估当前操作性能
        • 优化查询性能
        • 写操作性能
        • 说明结果
      • 分析查询表现
      • Tailable 游标
  • MongoDB聚合
    • 聚合管道
      • 聚合管道优化
      • 聚合管道限制
      • 聚合管道和分片集合
      • 使用 Zip Code 数据集进行聚合
      • 使用用户首选项数据进行聚合
    • Map-Reduce
      • Map-Reduce 和分片集合
      • Map-Reduce 并发
      • Map-Reduce 示例
      • 执行增量 Map-Reduce
      • 对 Map Function 进行故障排除
      • 排除 Reduce Function 问题
      • Map-Reduce转换到聚合管道
    • 聚合参考
      • 聚合管道快速参考
      • 聚合命令
      • 聚合命令对比
      • 聚合表达式中的变量
      • SQL 到聚合映射图表
  • MongoDB数据模型
    • 数据建模介绍
    • 模式验证
    • 数据模型设计
      • 一对一嵌套关系模型
  • MongoDB事务
  • MongoDB事务
    • 驱动程序 API
    • 生产注意事项
    • 生产注意事项 (分片集群)
    • 事务操作
  • MongoDB索引
    • 单字段索引
    • 复合索引
    • 多键索引
      • 多键索引范围
    • 文本索引
      • 为文本索引指定语言
      • 指定文本索引的名称
      • 用权重控制搜索结果
      • 限制扫描条目的数量
    • 通配符索引
      • 通配符索引限制
    • 2dsphere 索引
      • 查询一个2dsphere索引
    • 2d 索引
      • 创建一个2d索引
      • 查询一个2d索引
      • 2d索引内部
      • 使用球面几何计算距离
    • geoHaystack 索引
      • 创建Haystack索引
      • 查询Haystack索引
    • 哈希索引
    • 索引特性
      • TTL 索引
        • 通过设置TTL使集合中的数据过期
      • 唯一索引
      • 部分索引
      • 不分大小写索引
      • Sparse 索引
    • 在填充的集合上建立索引
      • 在副本集上建立滚动索引
      • 在分片群集上建立滚动索引
    • 索引交集
    • 管理索引
    • 衡量索引使用
    • 索引策略
      • 创建索引来支持查询
      • 使用索引对查询结果进行排序
      • 确保索引适合RAM
      • 创建以确保选择性的查询
    • 索引参考
  • MongoDB安全
    • 安全检查列表
    • 启用访问控制
    • 身份验证
      • 用户
        • 添加用户
        • 权限认证机制
          • SCRAM
            • 用x.509证书来认证客户端
    • 审计
      • 配置审计过滤器
      • 配置审计
      • 系统事件审计消息
    • 网络和配置强化
    • 安全参考
      • system.roles集合
      • system.users集合
      • 资源文档
      • 权限操作
    • 附录
      • 附录-A-用于测试的 OpenSSl CA 证书
      • 附录-B-用于测试的OpenSSL服务器证书
      • 附录-C-用于测试的OpenSSL客户端证书
  • Change Streams变更流
    • 变更流生产建议
    • 变更事件
  • MongoDB复制
    • 副本集成员
    • 副本集日志
    • 副本集数据同步
    • 副本集部署架构
    • 副本集成员配置教程
    • 副本集维护教程
    • MongoDB复制参考
  • MongoDB分片
    • 分片集群组件
    • 分片键
    • 哈希分片
    • 范围分片
    • 区
      • 管理分片区
      • 按位置细分数据
      • 用于更改SLA或SLO的分层硬件
      • 按应用或客户细分数据
      • 仅插入工作负载的分布式本地写入
      • 管理分片区
    • 使用块进行数据分区
      • 在分片集群中拆分数据块
    • 分片管理
      • 查看集群设置
    • 重启一个分片集群
    • [把一个分片集群迁移到不同的硬件](fen-pian/migrate-a -sharded-cluster-to-different-hardware.md)
    • 分片参考
  • MongoDB管理
    • 产品说明
    • 操作检查列表
    • 开发检查列表
    • 配置和维护
    • 性能
    • 数据中心意识
      • MongoDB部署中的工作负载隔离
      • 区
        • 管理分片区
        • 按位置细分数据
        • 用于更改SLA或SLO的分层硬件
        • 按应用或客户细分数据
        • 仅插入工作负载的分布式本地写入
        • 管理分片区
    • MongoDB备份方法
    • MongoDB监控
  • MongoDB存储
    • 存储引擎
      • WiredTiger 存储引擎
      • 内存存储引擎
    • 日志记录
      • 管理日志记录
        • GridFS
        • FAQ:MongoDB 存储
  • MongoDB参考
    • 运算符
      • 查询与映射运算符
        • 比较查询运算符
          • $eq
          • $gt
          • $gte
          • $in
          • $lt
          • $lte
          • $ne
          • $nin
        • 逻辑查询运算符
          • $and
          • $not
          • $nor
          • $or
        • 元素查询运算符
        • 评估查询运算符
        • 地理空间查询运算符
        • 数组查询运算符
        • 按位查询运算符
        • $comment
        • 映射运算符
      • 更新运算符
        • 字段更新运算符
        • 数组更新运算符
        • 按位更新运算符
      • 聚合管道阶段
      • 聚合管道操作符
        • $abs (aggregation)
        • $acos (aggregation)
        • $acosh (aggregation)
        • $add (aggregation)
        • $addToSet (aggregation)
        • $allElementsTrue (aggregation)
        • $and (aggregation)
        • $anyElementTrue (aggregation)
        • $arrayElemAt (aggregation)
        • $arrayToObject (aggregation)
        • $asin (aggregation)
        • $asinh (aggregation)
        • $atan (aggregation)
        • $atan2 (aggregation)
        • $atanh (aggregation)
        • $avg (aggregation)
        • $ceil (aggregation)
        • $cmp (aggregation)
        • $concat (aggregation)
        • $concatArrays (aggregation)
        • $cond (aggregation)
        • $convert (aggregation)
        • $cos (aggregation)
        • $dateFromParts (aggregation)
        • $dateToParts (aggregation)
        • $dateFromString (aggregation)
        • $literal (aggregation)
      • 查询修饰符
    • 数据库命令
      • 聚合命令
      • 地理空间命令
      • 查询和写操作命令
      • 查询计划缓存命令
      • 认证命令
      • 用户管理命令
      • 角色管理命令
      • 复制命令
      • 分片命令
      • 会话命令
      • 管理命令
      • 诊断命令
      • 免费监控命令
      • 系统事件审计命令
    • mongo Shell 方法
      • 集合方法
        • db.collection.aggregate()
        • db.collection.bulkWrite()
        • db.collection.copyTo()
        • db.collection.count()
        • db.collection.countDocuments()
        • db.collection.estimatedDocumentCount()
        • db.collection.createIndex()
        • db.collection.createIndexes()
        • db.collection.dataSize()
        • db.collection.deleteOne()
        • db.collection.deleteMany()
        • db.collection.distinct()
        • db.collection.drop()
        • db.collection.dropIndex()
        • db.collection.dropIndexes()
        • db.collection.ensureIndex()
        • db.collection.explain()
        • db.collection.find()
        • db.collection.findAndModify()
        • db.collection.findOne()
        • db.collection.findOneAndDelete()
        • db.collection.findOneAndReplace()
        • db.collection.findOneAndUpdate()
        • db.collection.getIndexes()
        • db.collection.getShardDistribution()
        • db.collection.getShardVersion()
        • db.collection.insert()
        • db.collection.insertOne()
        • db.collection.insertMany()
        • db.collection.isCapped()
        • db.collection.latencyStats()
        • db.collection.mapReduce()
        • db.collection.reIndex()
        • db.collection.remove()
        • db.collection.renameCollection()
        • db.collection.replaceOne()
        • db.collection.save()
        • db.collection.stats()
        • db.collection.storageSize()
        • db.collection.totalIndexSize()
        • db.collection.totalSize()
        • db.collection.update()
        • db.collection.updateOne()
        • db.collection.updateMany()
        • db.collection.watch()
        • db.collection.validate()
    • MongoDB中的限制与阈值
    • MongoDB系统集合
    • 词汇表
    • 默认的MongoDB端口
    • 默认的MongoDB读/写关注
    • 服务器会话
  • MongoDB FAQ
    • FAQ: MongoDB基础知识
    • FAQ: MongoDB索引
    • FAQ: MongoDB并发
    • FAQ: MongoDB分片
    • FAQ: MongoDB复制和副本集
    • FAQ: MongoDB存储
    • FAQ: MongoDB诊断
  • MongoDB 版本管理
  • 联系我们
    • Tapdata Cloud
    • MongoDB中文社区
    • 社区合作伙伴—锦木信息
由 GitBook 提供支持
在本页
  • map功能要求
  • reduce功能要求
  • 选项
  • 输出到集合
  • 输出到带有 Action 的 Collection
  • 输出内联
  • finalize功能要求
  • Map-Reduce 例子
  • 返回每位客户的总价格
  • 使用 Item 的平均数量计算 Order 和总数量
  • 输出
  • 限制
  • 附加信息
  1. MongoDB参考
  2. mongo Shell 方法
  3. 集合方法

db.collection.mapReduce()

上一页db.collection.latencyStats()下一页db.collection.reIndex()

最后更新于3年前

在本页面

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。该$projectsets:

    • 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

译者:李冠飞

校对:

map功能要求
reduce功能要求
选项
finalize功能要求
Map-Reduce 例子
输出
附加信息