whobutsb
whobutsb

Reputation: 1075

MongoDB MapReduce Emit Strangeness

I'm very much a noob when it comes to MapReduce and I have been pulling my hair out with this issue. Hopefully someone can give me a hand.

My Goal: Get the product revenue and a count of the units sold.

Transactions Collection sample document where i'm querying from:

 { "_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 ) }

As you can see I have an embedded array called Products with the ProductID, Product Price, and Product Quantity.

My Map Function

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()
                }); 

            }

        }); 
    }
}

So with this i'm only going to emit Transactions that were completed. If the Transaction was completed I'm looping through the Products array and if the Product.ProductID.$id is equal to the Product_ID that I set in the MapReduce Scope then I'm going to emit the Product from the set.

For testing sake I've set up my Reduce function as:

reduce = function(key, Product_Transactions){

    return {"Transactions" : Product_Transactions}; 

}

For some odd reason i'm getting this sort of result:

[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
                                        )

                            )
                       )
                   )
             )

I'm not sure why I'm getting this odd embedded array. The emit key is always the same and never changes. I'm really lost for ideas on where to start trouble shooting. Any help or guidance would be appreciated.

Upvotes: 0

Views: 1587

Answers (1)

Sergio Tulentsev
Sergio Tulentsev

Reputation: 230336

Output of map should be in the same format that reduce consumes and produces. The idea is that reduce may run in parallel and/or against partially reduced results.

Here's how your code should look like (pseudo-code)

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;
}

Upvotes: 1

Related Questions