当谈到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 ) }
正如您所看到的,我有一个名为Products的嵌入式数组,它包含ProductID、ProductPrice和ProductQuantity。
我的地图功能
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范围中设置的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
)
)
)
)
)
我不知道为什么我会得到这个奇怪的嵌入式数组。发射关键帧始终不变。我真的不知道从哪里开始解决问题。如有任何帮助或指导,我们将不胜感激。
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;
}