0

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

削減機能:

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であるのはなぜですか?

4

1 に答える 1

0

MongoDB の map/reduce は JavaScript に基づいているため、JavaScript の数値演算を使用します。これは、本質的に倍精度のIEEE 754 浮動小数点演算です。

浮動小数点数は (基本的に、詳細についてはウィキペディアの記事を参照してください) として格納されます。

mantissa * base ^ exponent

この場合、基数は 2 (基数 10 の浮動小数点数は と呼ばれますdecimal) であり、有理数を含む一部の数値は、値の精度が限られている場合、この形式で正確に表すことができません。

現状では、操作の最後に丸めを実行するのがおそらく最善の策です。残念ながら、すべての通貨に小数点以下 2 桁があるわけではないため、国際化が面倒になる可能性があります。また、四捨五入が重要になるリスクが依然としてあります。必ず、すべてのコンピューター科学者が浮動小数点演算について知っておくべきことを知っておいてください。

10gen の Jira でこの機能に投票することもできます。

于 2013-03-22T08:58:06.273 に答える