使用 MapReduce 的联合集 MongoDB
Union Set using MapReduce MongoDB
我正在尝试使用 MapReduce 合并两个集合。它们具有相同的结构,例如:
db.tableR.insert({product:"A", quantity:150});
db.tableR.insert({product:"B", quantity:100});
db.tableR.insert({product:"C", quantity:60});
db.tableR.insert({product:"D", quantity:200});
db.tableS.insert({product:"A", quantity:150});
db.tableS.insert({product:"B", quantity:100});
db.tableS.insert({product:"F", quantity:220});
db.tableS.insert({product:"G", quantity:130});
我希望 MapReduce 删除重复项。
我正在创建一个根据数量划分集合的地图:
map = function(){
if (this.quantity<150){
var key=0;
}else{
var key=1;
}
var value = {"product":this.product, "quantity":this.quantity};
emit(key,value);
};
现在我希望 reduce 函数删除重复项,但我找不到将新的添加到 reduced var 的方法。
这是我试过的:
reduce = function(keys,values){
var reduced = {
product:"",
quantity:""
};
for (var i=0; i < values.length;i++)
{
if(values[i].product !== null) {reduced.insert({product: values[i].product, quantity: values[i].quantity})}
}
return reduced;};
db.tableR.mapReduce(map,reduce,{out:'map_reduce_result'});
db.tableS.mapReduce(map,reduce,{out:'map_reduce_result'});
db.map_reduce_result.find();
我可以使用什么功能?
我的预期输出:
{"_id" : 0, "value" : {"product" : "B","quantity" : 100}}
{"_id" : 0, "value" : {"product" : "C","quantity" : 60}}
{"_id" : 0, "value" : {"product" : "G","quantity" : 130}}
{"_id" : 1, "value" : {"product" : "A","quantity" : 150}}
{"_id" : 1, "value" : {"product" : "D","quantity" : 200}}
{"_id" : 1, "value" : {"product" : "F","quantity" : 220}}
reduce 函数只能 return 单个值,因此您希望它对每一行都执行。 reduce 函数会为映射函数中的每个唯一键 return 调用。您的键是 0 和 1,因此每个集合只会调用两次 - 一次是键 0,一次是键 1。因此,每个集合的最大结果数仅为 2。
您需要做的是在map函数中设置产品的key:
map = function(){
emit(this.product,{product:this.product,quantity:this.quantity});
};
现在,将为每个唯一产品值调用 reduce 函数。我们的新 map 函数只是 returns 数组中的第一个值(如果在同一个集合中有重复项,它只会取第一个。你可以在这里聪明一点,取最高或最低数量 - 或者数量等)。
reduce = function(keys,values){
return values[0];
};
运行 你的第一个 map reduce 作业:
db.tableR.mapReduce(map,reduce,{out:'map_reduce_result'});
运行 你的第二个,但这次 merge
结果:
db.tableS.mapReduce(map,reduce,{out: {merge: 'map_reduce_result'}});
现在db.map_reduce_result.find()
returns:
{ "_id" : "A", "value" : { "product" : "A", "quantity" : 150 } }
{ "_id" : "B", "value" : { "product" : "B", "quantity" : 100 } }
{ "_id" : "C", "value" : { "product" : "C", "quantity" : 60 } }
{ "_id" : "D", "value" : { "product" : "D", "quantity" : 200 } }
{ "_id" : "F", "value" : { "product" : "F", "quantity" : 220 } }
{ "_id" : "G", "value" : { "product" : "G", "quantity" : 130 } }
显然 _id
与您要查找的内容不匹配。如果你绝对需要,你可以像这样使用聚合框架:
db.map_reduce_result.aggregate([{$project:{
_id:{$cond: { if: { $gte: [ "$value.quantity", 150 ] }, then: 1, else: 0 }},
value:1
}}]);
这导致:
{ "_id" : 1, "value" : { "product" : "A", "quantity" : 150 } }
{ "_id" : 0, "value" : { "product" : "B", "quantity" : 100 } }
{ "_id" : 0, "value" : { "product" : "C", "quantity" : 60 } }
{ "_id" : 1, "value" : { "product" : "D", "quantity" : 200 } }
{ "_id" : 1, "value" : { "product" : "F", "quantity" : 220 } }
{ "_id" : 0, "value" : { "product" : "G", "quantity" : 130 } }
注意:如果来自不同集合的两行具有相同的产品 ID,但数量不同,我不确定哪一个将被 returned。
我正在尝试使用 MapReduce 合并两个集合。它们具有相同的结构,例如:
db.tableR.insert({product:"A", quantity:150});
db.tableR.insert({product:"B", quantity:100});
db.tableR.insert({product:"C", quantity:60});
db.tableR.insert({product:"D", quantity:200});
db.tableS.insert({product:"A", quantity:150});
db.tableS.insert({product:"B", quantity:100});
db.tableS.insert({product:"F", quantity:220});
db.tableS.insert({product:"G", quantity:130});
我希望 MapReduce 删除重复项。
我正在创建一个根据数量划分集合的地图:
map = function(){
if (this.quantity<150){
var key=0;
}else{
var key=1;
}
var value = {"product":this.product, "quantity":this.quantity};
emit(key,value);
};
现在我希望 reduce 函数删除重复项,但我找不到将新的添加到 reduced var 的方法。
这是我试过的:
reduce = function(keys,values){
var reduced = {
product:"",
quantity:""
};
for (var i=0; i < values.length;i++)
{
if(values[i].product !== null) {reduced.insert({product: values[i].product, quantity: values[i].quantity})}
}
return reduced;};
db.tableR.mapReduce(map,reduce,{out:'map_reduce_result'});
db.tableS.mapReduce(map,reduce,{out:'map_reduce_result'});
db.map_reduce_result.find();
我可以使用什么功能?
我的预期输出:
{"_id" : 0, "value" : {"product" : "B","quantity" : 100}}
{"_id" : 0, "value" : {"product" : "C","quantity" : 60}}
{"_id" : 0, "value" : {"product" : "G","quantity" : 130}}
{"_id" : 1, "value" : {"product" : "A","quantity" : 150}}
{"_id" : 1, "value" : {"product" : "D","quantity" : 200}}
{"_id" : 1, "value" : {"product" : "F","quantity" : 220}}
reduce 函数只能 return 单个值,因此您希望它对每一行都执行。 reduce 函数会为映射函数中的每个唯一键 return 调用。您的键是 0 和 1,因此每个集合只会调用两次 - 一次是键 0,一次是键 1。因此,每个集合的最大结果数仅为 2。
您需要做的是在map函数中设置产品的key:
map = function(){
emit(this.product,{product:this.product,quantity:this.quantity});
};
现在,将为每个唯一产品值调用 reduce 函数。我们的新 map 函数只是 returns 数组中的第一个值(如果在同一个集合中有重复项,它只会取第一个。你可以在这里聪明一点,取最高或最低数量 - 或者数量等)。
reduce = function(keys,values){
return values[0];
};
运行 你的第一个 map reduce 作业:
db.tableR.mapReduce(map,reduce,{out:'map_reduce_result'});
运行 你的第二个,但这次 merge
结果:
db.tableS.mapReduce(map,reduce,{out: {merge: 'map_reduce_result'}});
现在db.map_reduce_result.find()
returns:
{ "_id" : "A", "value" : { "product" : "A", "quantity" : 150 } }
{ "_id" : "B", "value" : { "product" : "B", "quantity" : 100 } }
{ "_id" : "C", "value" : { "product" : "C", "quantity" : 60 } }
{ "_id" : "D", "value" : { "product" : "D", "quantity" : 200 } }
{ "_id" : "F", "value" : { "product" : "F", "quantity" : 220 } }
{ "_id" : "G", "value" : { "product" : "G", "quantity" : 130 } }
显然 _id
与您要查找的内容不匹配。如果你绝对需要,你可以像这样使用聚合框架:
db.map_reduce_result.aggregate([{$project:{
_id:{$cond: { if: { $gte: [ "$value.quantity", 150 ] }, then: 1, else: 0 }},
value:1
}}]);
这导致:
{ "_id" : 1, "value" : { "product" : "A", "quantity" : 150 } }
{ "_id" : 0, "value" : { "product" : "B", "quantity" : 100 } }
{ "_id" : 0, "value" : { "product" : "C", "quantity" : 60 } }
{ "_id" : 1, "value" : { "product" : "D", "quantity" : 200 } }
{ "_id" : 1, "value" : { "product" : "F", "quantity" : 220 } }
{ "_id" : 0, "value" : { "product" : "G", "quantity" : 130 } }
注意:如果来自不同集合的两行具有相同的产品 ID,但数量不同,我不确定哪一个将被 returned。