我已经从csv导入了具有以下信息的数据库:
(这是csv:https://www.kaggle.com/jboysen/global-food-prices)
csv中的字符串按以下方式排序:
我需要针对每个国家/地区,每种产品显示最高价格。
我写道:
1)包含关键国家/地区和商品以及价格价格的地图
var map = function() {
emit({country: this.country_name, commodity: this.commodity_name}, {price: this.price});
};
2)一种减少功能,可扫描与钥匙相关的价格并查看最高价格
var reduce = function(key, values) {
var maxPrice = 0.0;
values.forEach(function(doc) {
var thisPrice = parseFloat(doc.price);
if( typeof doc.price != "undefined") {
if (thisPrice > maxPrice) {
maxPrice = thisPrice;
}
}
});
return {max_price: maxPrice};
};
3)我将地图的约简发送到集合“ mr”
db.prices.mapReduce(map, reduce, {out: "mr"});
问题:
例如,如果我打开csv并通过以下方式手动订购:
我可以检查一下(以举例说明)在阿富汗,商品面包的最高价格是65.25
但是,当我检查M-R时,得出阿富汗面包最高价格为0。
发生了什么
csv中有10个区域记录了为阿富汗记录的面包。 我在reduce的最后一行添加了:
print("reduce with key: " + key.country + ", " + key.commodity + "; max price: " + maxPrice);
从理论上讲,如果我在mongodb日志中进行搜索,则应该只找到一个带有“减少键:阿富汗,面包;最高价格:???”的入口。 取而代之的是,我看到十行(区域的相同编号),每行具有不同的最高价格。 最后一个具有“最高价格0”。
我的假设:
似乎在发出之后,当调用reduce时,它不是在寻找具有相同密钥的所有k-v对,而是考虑了混杂的子组。
因此,回顾一下我在csv结构上的入门示例:
我是否必须进行重新缩减以处理所有部分归约作业?
答案 0 :(得分:0)
我设法解决了这个问题。 MongoDB不一定要一口气就减少所有具有相同密钥的k-v对。
可能发生(在这种情况下)MongoDB将对与特定键相关的kv对的子集执行约简,然后在对第二个约简进行第二次约简时将发送该第一个约简的输出与同一键相关的子集。
我的代码无法正常工作,因为:
有2种方法可以解决此问题:
1)您为reduce输出变量使用与发出输出值相同的名称
2)您索引选择为键的属性,并在mapReduce()上使用“ sort”选项,以便与键相关的所有k-v对都可以一次性减少
第二种方法是,如果您不想放弃使用其他名称作为化简输出的名称(另外,由于每个键只进行一个化简,它具有更好的性能)。