当count == 1时,MapReduce给出奇数结果

时间:2014-11-26 18:18:45

标签: mongodb mapreduce mongoid

Stack: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 / Reduce代码:

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">]

然后Map / Reduce结果为:

 => [{"_id"=>"547612531dbe8b4a7200006a", "value"=>{"ObjectId(\"547612441dbe8bf35b000005\")"=>2.0}}]

请注意,value键指向{"ObjectID" => Number}形式的哈希值。这是应该的。

现在让我们说一份奖金文件:

> Bonus.count
 => 1
> Bonus.first
 => #<Bonus _id: 547612a21dbe8b7859000071, giver_id: "547612441dbe8bf35b000005", receiver_id: "547612531dbe8b4a7200006a">

然后Map / Reduce结果为:

 => [{"_id"=>"547612531dbe8b4a7200006a", "value"=>"547612441dbe8bf35b000005"}]

请注意,结果的架构已更改。它应该是:

 => [{"_id"=>"547612531dbe8b4a7200006a", "value"=>{"ObjectId(\"547612441dbe8bf35b000005\")"=>1.0}}]

这里发生了什么?

1 个答案:

答案 0 :(得分:1)

来自docs

  

MongoDB不会为只有一个密钥的密钥调用reduce函数   单一价值。 values参数是一个数组,其元素是   值“映射”到键的对象。

在第一种情况下,密钥this.receiver_id在其组中有两个文档,因此为该密钥调用reduce函数。

在第二种情况下,当您的emitted键在其组中只有一个记录时,根本不会调用reduce函数

因此,您为密钥发出的值(this.giver_id)将在不减少的情况下显示为已发送,不需要进一步减少。