Map/Reduce
Mongoid 提供了围绕 MongoDB 的 map/reduce 框架的 DSL,用于执行自定义的 map/reduce 作业或简单的聚合。
注意
map-reduce 操作已被弃用。建议使用聚合框架,它比 map-reduce 操作提供更好的性能和可用性,应优先考虑用于新开发。
执行
您可以通过调用map_reduce
并提供 map 和 reduce JavaScript 函数来告诉 Mongoid 对一个类或一个标准进行 map/reduce 操作。
map = %Q{ function() { emit(this.name, { likes: this.likes }); } } reduce = %Q{ function(key, values) { var result = { likes: 0 }; values.forEach(function(value) { result.likes += value.likes; }); return result; } } Band.where(:likes.gt => 100).map_reduce(map, reduce).out(inline: 1)
与标准一样,map/reduce 调用是惰性评估的。除非您迭代结果或对包装器进行调用以强制数据库访问,否则不会对数据库进行任何操作。
Band.map_reduce(map, reduce).out(replace: "mr-results").each do |document| p document # { "_id" => "Tool", "value" => { "likes" => 200 }} end
除了 map/reduce,您还必须提供结果的输出位置。如果不提供此信息,将引发错误。有效的 #out
选项有
inline: 1
:不要将输出存储在集合中。replace: "name"
:在提供的名称的集合中存储,并覆盖其中存在的任何文档。merge: "name"
:在提供的名称的集合中存储,并将结果与现有文档合并。reduce: "name"
:在提供的名称的集合中存储,并减少该集合中所有现有结果。
原始结果
可以通过 execute
方法或其别名 raw
和 results
获取 Map/Reduce 执行的结果。
mr = Band.where(:likes.gt => 100).map_reduce(map, reduce).out(inline: 1) mr.execute # => {"results"=>[{"_id"=>"Tool", "value"=>{"likes"=>200.0}}], "timeMillis"=>14, "counts"=>{"input"=>4, "emit"=>4, "reduce"=>1, "output"=>1}, "ok"=>1.0, "$clusterTime"=>{"clusterTime"=>#<BSON::Timestamp:0x00005633c2c2ad20 @seconds=1590105400, @increment=1>, "signature"=>{"hash"=><BSON::Binary:0x12240 type=generic data=0x0000000000000000...>, "keyId"=>0}}, "operationTime"=>#<BSON::Timestamp:0x00005633c2c2aaf0 @seconds=1590105400, @increment=1>}
统计
MongoDB 4.2及以下版本的数据库提供Map/Reduce执行统计信息。从MongoDB 4.4版本开始,Map/Reduce通过聚合管道实现,本节中描述的统计信息不可用。
在MapReduce
对象上提供了以下方法
counts
:通过管道读取、发射、减少和输出的文档数量。input
、emitted
、reduced
、output
:单独的计数方法。请注意,emitted
和reduced
方法的命名与counts
中的哈希键不同。time
:Map/Reduce管道执行所需的时间,以毫秒为单位。
以下代码说明了如何检索统计信息
mr = Band.where(:likes.gt => 100).map_reduce(map, reduce).out(inline: 1) mr.counts # => {"input"=>4, "emit"=>4, "reduce"=>1, "output"=>1} mr.input # => 4 mr.emitted # => 4 mr.reduced # => 1 mr.output # => 1 mr.time # => 14
注意
每次调用统计方法都会重新执行Map/Reduce管道。执行结果不会被Mongoid存储。如果需要多个统计信息,请考虑使用execute
方法检索原始结果,并从原始结果中获取统计信息。