我为mongodb写了一个mapreduce,但结果有一些问题
日期:
mongos> db.perGoods.find()
{ "_id" : ObjectId("514bf6428f43a9fee9cef526"), "id" : 1, "goods_id" : "1234", "keywords" : [ { "keyword" : "lianyiqun", "price" : 3.52 }, { "keyword" : "nvzhuang", "price" : 4.27 }, { "keyword" : "chunkuan", "price" : 3.12 }, { "keyword" : "chaoliu", "price" : 8.32 }, { "keyword" : "duanzhuang", "price" : 4.92 } ] }
{ "_id" : ObjectId("514bf65d8f43a9fee9cef527"), "id" : 2, "goods_id" : "5678", "keywords" : [ { "keyword" : "lianyiqun", "price" : 9.26 }, { "keyword" : "nvzhuang", "price" : 4.52 } ] }
{ "_id" : ObjectId("514bf6768f43a9fee9cef528"), "id" : 3, "goods_id" : "5612", "keywords" : [ { "keyword" : "lianyiqun", "price" : 7.42 }, { "keyword" : "nvzhuang", "price" : 6.52 } ] }
{ "_id" : ObjectId("514bf6968f43a9fee9cef529"), "id" : 4, "goods_id" : "9612", "keywords" : [ { "keyword" : "lianyiqun", "price" : 3.12 }, { "keyword" : "nvzhuang", "price" : 6.57 }, { "keyword" : "chunzhuang", "price" : 5.55 } ] }
地图功能:
mongos> var mapFunction = function() {
... for (var index = 0; index < this.keywords.length; index++) {
... var key = this.goods_id;
... var value = {
... count: 1,
... price: this.keywords[index].price
... };
... emit(key, value);
... }
... };
reduce函数:
mongos> var reduceFunction = function(key, priceCountObjects) {
... reducedValue = { count: 0, sumprice: 0 };
...
... for (var index = 0; index < priceCountObjects.length; index++) {
... reducedValue.count += priceCountObjects[index].count;
... reducedValue.sumprice += priceCountObjects[index].price;
... }
...
... return reducedValue;
... };
代码:
mongos> db.perGoods.mapReduce(
... mapFunction,
... reduceFunction,
... { out: "map_reduce_test" }
... )
{
"result" : "map_reduce_test",
"timeMillis" : 5,
"counts" : {
"input" : 4,
"emit" : 12,
"reduce" : 4,
"output" : 4
},
"ok" : 1,
}
结果:
mongos> db.map_reduce_test.find()
{ "_id" : "1234", "value" : { "count" : 5, "sumprice" : 24.15 } }
{ "_id" : "5612", "value" : { "count" : 2, "sumprice" : 13.94 } }
{ "_id" : "5678", "value" : { "count" : 2, "sumprice" : 13.78 } }
{ "_id" : "9612", "value" : { "count" : 3, "sumprice" : 15.240000000000002 } }
mongos>
为什么最后的结果是15.240000000000002?
答案 0 :(得分:0)
由于MongoDB中的map / reduce基于JavaScript,因此它使用JavaScript的number arithmetic,这实际上是双精度IEEE 754 floating point arithmetic。
浮点数(基本上,有关详细信息,请参阅维基百科文章)存储为</ p>
mantissa * base ^ exponent
在这种情况下,base为2(基数为10的浮点数称为decimal
),如果值的精度有限,则某些数字(包括有理数)根本无法以此格式表示。
目前看来,最好的选择可能是在操作结束时进行四舍五入。不幸的是,并非所有货币都有两个小数位,因此国际化可能会变得很痛苦,并且仍然存在舍入变得重要的风险 - 确保你知道What Every Computer Scientist Should Know About Floating-Point Arithmetic