2012-02-17 87 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