2012-02-17 61 views
0

当谈到MapReduce时,我非常喜欢noob,而我一直在用这个问题拉我的头发。希望有人能帮我一把。MongoDB MapReduce发出奇怪

我的目标:获得产品收入和销售单位的数量。

交易收集样本文档了我来自查询:

{ "_id" : ObjectId("xxxxxxxxxx"), 
    "MerchantID" : { "$ref" : "merchants", 
    "$id" : ObjectId("xxxxxxxx") }, 
    "TransactionSocialKey" : "xxxxxxxx", 
    "PurchaseComplete: true, 
    "Products" : [ 
    { "ProductID" : { "$ref" : "products", 
     "$id" : ObjectId("4ecae2b9cf72ab1f6900xxx1") }, 
     "ProductPrice" : 14.99, 
     "ProductQuantity" : "1" }, 
    { "ProductID" : { "$ref" : "products", 
     "$id" : ObjectId("4ecae2b9cf72ab1f690xxx2") }, 
     "ProductPrice" : 14.99, 
     "ProductQuantity" : "1" } ], 
    "DateTimeCreated" : Date(1321919161000) } 

正如你可以看到我有所谓的产品与产品ID,产品价格和产品数量的嵌入式阵列。

我的地图功能,所以有了这个,我想只发出了完成的事务

map = function(){ 

    if(this.PurchaseComplete === true){ 

     this.Products.forEach(function(Product){ 

      if(Product.ProductID.$id.toString() == Product_ID.toString()){ 

       emit(Product_ID, { 
        "ProductQuantity" : Product.ProductQuantity, 
        "ProductPrice" : Product.ProductPrice, 
        "ProductID" : Product.ProductID.$id.toString() 
       }); 

      } 

     }); 
    } 
} 

。如果事务已完成,我循环访问Products数组,如果Product.ProductID。$ id等于我在MapReduce Scope中设置的Product_ID,那么我将从该集合中发出Product。

为了测试的缘故,我已经建立了我的Reduce函数为:

reduce = function(key, Product_Transactions){ 

    return {"Transactions" : Product_Transactions}; 

} 

对于一些奇怪的原因,我得到这个排序结果的:

[results] => Array 
     (
      [0] => Array 
       (
        [_id] => MongoId Object 
         (
          [$id] => 4ecae2b9cf72ab1f6900xxx1 
         ) 

        [value] => Array 
         (
          [Transactions] => Array 
           (
            [0] => Array 
             (
              [Transactions] => Array 
               (
                [0] => Array 
                 (
                  [ProductQuantity] => 1 
                  [ProductPrice] => 14.99 
                  [ProductID] => 4ecae2b9cf72ab1f6900xxx1 
                 ) 

                [1] => Array 
                 (
                  [ProductQuantity] => 1 
                  [ProductPrice] => 14.99 
                  [ProductID] => 4ecae2b9cf72ab1f6900xxx1 
                 ) 

                 It Continues… 
               ) 
             ) 
            [1] => Array 
             (
              [ProductQuantity] => 1 
              [ProductPrice] => 12.74 
              [ProductID] => 4ecae2b9cf72ab1f6900xxx1 
             ) 

            [2] => Array 
             (
              [ProductQuantity] => 1 
              [ProductPrice] => 12.74 
              [ProductID] => 4ecae2b9cf72ab1f6900xxx1 
             ) 

          ) 
         ) 
        ) 
      ) 

我不知道为什么我收到了这个奇怪的嵌入式数组。发射键总是相同的,永远不会改变。我真的很想知道从哪里开始解决问题。任何帮助或指导,将不胜感激。

回答

1

map的输出格式应与reduce消耗和生成的格式相同。这个想法是reduce可以并行运行和/或针对部分减少的结果。

这里是你的代码应该怎么看起来像(伪代码)

var map = function() { 
    if(some condition) { 
    emit(product_id, {Transactions: [{ // <= note the array here! 
         "ProductQuantity" : Product.ProductQuantity, 
         "ProductPrice" : Product.ProductPrice, 
         "ProductID" : ID 
        }]}) 
    } 
}; 

var reduce = function(key, vals) { 
    var result = {Transactions: []}; 

    vals.forEach(function(v) { 
    v.Transactions.forEach(t) { 
     result.Transactions.push(t); 
    } 
    }); 

    return result; 
} 
+0

谢谢你这么多的快速回复。我会乱搞你的建议,看看这是否能让我得到任何地方。 – whobutsb 2012-02-17 21:35:57

+0

我想我的一个重要问题就是,为什么排放会产生一个多维数组?我真的只是在寻找一个一维关联数组。我不明白为什么有两个交易密钥。 – whobutsb 2012-02-17 23:16:28

+0

排放工作正常。这是你的减少,把事情搞砸了。你有没有尝试我的建议? – 2012-02-17 23:49:03