堆栈:MongoDB 2.6.5,Mongoid 3.1.6,Ruby 2.1.1
我正在使用Mongoid来做一些MongoDB Map/Reduce的东西。
这是设置:
class User
include Mongoid::Document
has_many :given_bonuses, class_name: 'Bonus', inverse_of: :giver
has_many :received_bonuses, class_name: 'Bonus', inverse_of: :receiver
end
class Bonus
include Mongoid::Document
belongs_to :giver, class_name: 'User', inverse_of: :given_bonuses
belongs_to :receiver, class_name: 'User', inverse_of: :received_bonuses
end
我正在使用以下映射/减少代码:
map = %Q{
function() {
emit(this.receiver_id, this.giver_id)
}
}
reduce = %Q{
function(key, values) {
var result = {};
values.forEach(function(value) {
if(! result[value]) {
result[value] = 0;
}
result[value] += 1;
});
return result;
}
}
Bonus.all.map_reduce(map, reduce).out(inline: 1)
假设我有两个或更多奖金文件:
> Bonus.count
=> 2
> Bonus.all.to_a
=> [#<Bonus _id: 547612a21dbe8b7859000071, giver_id: "547612441dbe8bf35b000005", receiver_id: "547612531dbe8b4a7200006a">, #<Bonus _id: 547612a21dbe8b78590000f9, giver_id: "547612441dbe8bf35b000005", receiver_id: "547612531dbe8b4a7200006a">]
然后映射/减少结果为:
=> [{"_id"=>"547612531dbe8b4a7200006a", "value"=>{"ObjectId("547612441dbe8bf35b000005")"=>2.0}}]
请注意,value
键指向形式为 {"ObjectID" => Number}
的哈希。这是应该的。
现在假设我只有一个奖励文件:
> Bonus.count
=> 1
> Bonus.first
=> #<Bonus _id: 547612a21dbe8b7859000071, giver_id: "547612441dbe8bf35b000005", receiver_id: "547612531dbe8b4a7200006a">
然后映射/减少结果为:
=> [{"_id"=>"547612531dbe8b4a7200006a", "value"=>"547612441dbe8bf35b000005"}]
请注意,结果的架构已更改。它应该是:
=> [{"_id"=>"547612531dbe8b4a7200006a", "value"=>{"ObjectId("547612441dbe8bf35b000005")"=>1.0}}]
这是怎么回事?
从文档中:
MongoDB不会为只有 单个值。values 参数是一个数组,其元素是 "映射"到键的值对象。
在第一种情况下,键this.receiver_id
的组中有两个文档,因此为该键调用了reduce函数。
在第二种情况下,当 emitted
键的组中只有一条记录时,根本不会调用 reduce 函数。
因此,您为密钥发出的值( this.giver_id
)显示为发出而不减少,无需进一步减少。