복붙노트

[MONGODB] MongoDB의 통합 프레임 워크를 사용하여 소수점 이하 2 자리까지 반올림

MONGODB

MongoDB의 통합 프레임 워크를 사용하여 소수점 이하 2 자리까지 반올림

나는 MongoDB의 통합 프레임 워크를 사용하여 아래와 같이 몇 가지 계산을하고있는 중이 야

db.RptAgg.aggregate( 
{ $group :
 { _id : {Region:"$RegionTxt",Mth:"$Month"},           
   ActSls:{$sum:"$ActSls"},
   PlnSls:{$sum:"$PlnSls"}
 } 
},
{ $project : 
 {
   ActSls:1,
   PlnSls:1,
   ActToPln:{$cond:[{ $ne: ["$PlnSls", 0] },{$multiply:[{$divide: ['$ActSls', '$PlnSls']},100]},0]}
  }

}

); 

나는 2 소수점 내 결과를 반올림하는 가장 쉬운 방법이 무엇인지 알아 내려고 노력하고있다. 다음은 내 결과입니다

{
    "result" : [
            {
                    "_id" : {
                            "Region" : "East",
                            "Mth" : 201301
                    },
                    "ActSls" : 72,
                    "PlnSls" : 102,
                    "ActToPln" : 70.58823529411765
            }
    ],
    "ok" : 1

}

aggegation 프레임 워크 자체의 결과에 70.58823529411765 : 내가 대신 "ActToPln"의 70.59을 보여주기 위해 "ActToPln"를 원한다. 난 내 응용 프로그램에서 라운딩을하고 피하려고

당신은 같은 도움을 기쁘게 할 수 있습니다.

다음은 내가 사용하는 데이터 세트입니다.

{
    "_id" : ObjectId("51d67ef69557c507cb172572"),
    "RegionTxt" : "East",
    "Month" : 201301,
    "Date" : "2013-01-01",
    "ActSls" : 31,
    "PlnSls" : 51
}
{
    "_id" : ObjectId("51d67ef69557c507cb172573"),
    "RegionTxt" : "East",
    "Month" : 201301,
    "Date" : "2013-01-02",
    "ActSls" : 41,
    "PlnSls" : 51
}

미리 감사드립니다. 남도

해결법

  1. ==============================

    1.아무 $ 라운드 연산자는 없지만 당신은 통합 프레임 워크에서이 작업을 수행 할 수 있습니다 - 일반적으로 부동 소수점 정밀도 문제를 방지합니다 특정 순서로 그 일을.

    아무 $ 라운드 연산자는 없지만 당신은 통합 프레임 워크에서이 작업을 수행 할 수 있습니다 - 일반적으로 부동 소수점 정밀도 문제를 방지합니다 특정 순서로 그 일을.

    > db.a.save({x:1.23456789})
    > db.a.save({x:9.87654321})
    > db.a.aggregate([{$project:{ _id:0, 
             y:{$divide:[
                  {$subtract:[
                          {$multiply:['$x',100]},
                          {$mod:[{$multiply:['$x',100]}, 1]}
                  ]},
                  100]}
    }}])
    { "y" : 1.23 }
    { "y" : 9.87 }
    

    문제의 기존 파이프 라인을 감안할 때, 대체 :

    {$multiply:[{$divide: ['$ActSls', '$PlnSls']},100]}
    

    {$divide:[
         {$subtract:[ 
              {$multiply:[
                 {$divide: ['$ActSls','$PlnSls']},
                 10000
              ]}, 
              {$mod:[
                 {$multiply:[{$divide: ['$ActSls','$PlnSls']}, 10000 ]},
                 1]}
              ]}, 
         100
    ]}
    

    샘플 데이터 포인트로이 결과입니다 :

    { "ActSls" : 31, "PlnSls" : 51, "ActToPln" : 60.78 }
    { "ActSls" : 41, "PlnSls" : 51, "ActToPln" : 80.39 }
    { "ActSls" : 72, "PlnSls" : 102, "ActToPln" : 70.58 }
    
  2. ==============================

    2.몽고 내내 작품의 좋은. 내가 찾은 가장 깨끗한 방법.

    몽고 내내 작품의 좋은. 내가 찾은 가장 깨끗한 방법.

    수는 3.3333333이다 말

    var round = require('mongo-round');
    
    db.myCollection.aggregate([
        { $project: {
            roundAmount: round('$amount', 2)  // it will become 3.33
        } }
    ]);
    
  3. ==============================

    3.몽고 4.2 시작, 지정된 소수 자릿수에 특정 정밀도로 숫자를 반올림하는 데 사용할 수있는 새로운 $ 라운드 집계 연산자가있다 :

    몽고 4.2 시작, 지정된 소수 자릿수에 특정 정밀도로 숫자를 반올림하는 데 사용할 수있는 새로운 $ 라운드 집계 연산자가있다 :

    집계 파이프 라인 (소수점 이하 2 자리까지 여기에 우리 라운드 XS) 내에서 같은 사용할 수있는 :

    // db.collection.insert([{x: 1.23456}, {x: 9.87654}, {x: 0.055543}, {x: 12.345}])
    db.collection.aggregate([{ $project: { "rounded_x": { $round: ["$x", 2] }}}])
    // [{"rounded_x": 1.23}, {"rounded_x": 9.88}, {"rounded_x": 0.06}, {"rounded_x": 12.35}]
    

    장소 파라미터는 선택적이며 (즉 라운딩 0 소수점 AT)는 전체 정수로 라운딩을 초래 생략합니다.

  4. ==============================

    4.이 솔루션은 제대로 2DP 아래로 반올림합니다 :

    이 솔루션은 제대로 2DP 아래로 반올림합니다 :

    "rounded" : {
      $subtract:[
        {$add:['$absolute',0.0049999999999999999]},
        {$mod:[{$add:['$absolute',0.0049999999999999999]}, 0.01]}
      ]
    }
    

    예를 들어이 1.25-1.2499 위쪽으로하지만, 1.25-1.2501 아래로 반올림합니다.

    노트:

  5. ==============================

    5.왜 그런지 모르겠지만 (이 페이지에서) 모든 해답은 12.345 나에게 12.34를 제공합니다. 그래서 난 내 자신의 프로젝트 단계를 썼다 :

    왜 그런지 모르겠지만 (이 페이지에서) 모든 해답은 12.345 나에게 12.34를 제공합니다. 그래서 난 내 자신의 프로젝트 단계를 썼다 :

    x = 12.345
    
    {'$project': {
        y: {'$divide': [{'$trunc': {'$add': [{'$multiply': ['$x', 100]}, 0.5]}}, 100]},
    }},
    

    그것은 12.35을 제공합니다.

    여기에 간단한 산술, 속임수입니다 :

    그러나, (내 집계 충분했다) 네거티브 제대로 작동하지 않습니다. 모두 (양극과 음극)의 경우를 들어 당신은 복근과 함께 사용한다 :

    {'$project': {
        z: {'$multiply': [
            {'$divide': ['$x', {'$abs': '$x'}]}, 
            {'$divide': [{'$trunc': {'$add': [{'$multiply': [{'$abs': '$x'}, 100]}, 0.5]}}, 100]}
        ]},
    }}
    

    저는 여기에, 수의 기호를 얻을 복근에 의해 원래의 수를 포장하고 다중 출력을 반올림에 의해 서명.

  6. ==============================

    6.집계 프레임 워크의 현재 버전에는 라운드 운영자가 없습니다. 이 조각을 시도 할 수 있습니다 :

    집계 프레임 워크의 현재 버전에는 라운드 운영자가 없습니다. 이 조각을 시도 할 수 있습니다 :

    > db.a.save({x:1.23456789})
    > db.a.save({x:9.87654321})
    > db.a.aggregate([{$project:{y:{$subtract:['$x',{$mod:['$x', 0.01]}]}}}])
    {
        "result" : [
            {
                "_id" : ObjectId("51d72eab32549f94da161448"),
                "y" : 1.23
            },
            {
                "_id" : ObjectId("51d72ebe32549f94da161449"),
                "y" : 9.870000000000001
            }
        ],
        "ok" : 1
    }
    

    하지만 보시다시피,이 솔루션은 잘 때문에 정밀도 문제로 작동하지 않습니다. 이 경우 가장 쉬운 방법은 응용 프로그램에서 wiredprairie의 조언과 메이크업 라운드 @ 따르는 것입니다.

  7. ==============================

    7.

    rounded:{'$multiply': [{ "$cond": [{ "$gte": [ "$x", 0 ] }, 1,-1 ]},{'$divide': [{'$trunc': {'$add': [{'$multiply': [{'$abs': '$x'}, {$pow:[10,2]}]}, 0.5]}}, {$pow:[10,2]}]}]}
    

    egvo의 솔루션은 시원하지만이 0이면 0으로 나누기를 제공합니다. $ 콘드을 방지하기 위해 기호를 감지하는 데 사용할 수 있습니다

    (FIELD_NAME 원하는 10 진수 번호 2 X 교환)

  8. ==============================

    8.내가 그것의 수치 MongoDB를이 기능이 누락되어 있다고 가정 해 봅시다. 나는 그들이 곧 추가됩니다 호핑하고있다.

    내가 그것의 수치 MongoDB를이 기능이 누락되어 있다고 가정 해 봅시다. 나는 그들이 곧 추가됩니다 호핑하고있다.

    그러나, 나는 긴 집계 파이프 라인을 함께했다. 시인, 그것은 효율적하지 않을 수 있지만, 반올림의 규칙을 존중.

    db.t.aggregate([{
        $project: {
            _id: 0,
            number: {
                $let: {
                    vars: {
                        factor: {
                            $pow: [10, 3]
                        },
                    },
                    in: {
                        $let: {
                            vars: {
                                num: {$multiply: ["$$factor", "$number"]},
                            },
                            in: {
                                $switch: {
                                    branches: [
                                        {case: {$gte: ["$$num", {$add: [{$floor: "$$num"}, 0.5]}]}, then: {$divide:[ {$add: [{$floor: "$$num"}, 1.0]},"$$factor"]}},
                                        {case: {$lt: ["$$num", {$add: [{$floor: "$$num"}, 0.5]}]}, then: {$divide:[{$floor: "$$num"}, "$$factor"]}}                                    
                                    ]
                                }
                            }
                        }
                    }
                }
            }
        }
    }])
    

    이제 가정 해 보자, 나는 내 컬렉션의 이름 t에 다음의 서류를

    { number" : 2.341567 }
    { number" : 2.0012 }
    { number" : 2.0012223 }
    

    쿼리 이상 실행 한 후, 나는 가지고 :

    { "number" : 2.342 }
    { "number" : 2.001 }
    { "number" : 2.001 }
    
  9. ==============================

    9.

    {$divide:[
                {$cond: { if: { $gte: [ {$mod:[{$multiply:['$dollarAmount',100]}, 1]}, 0.5 ] }, then: {$add: [{$subtract:[
                      {$multiply:['$dollarAmount',100]},
                      {$mod:[{$multiply:['$dollarAmount',100]}, 1]}
              ]}
                    ,1]}, else: {$subtract:[
                      {$multiply:['$dollarAmount',100]},
                      {$mod:[{$multiply:['$dollarAmount',100]}, 1]}
              ]} }}
              , 
              100]}
    

    희망이 하나가 반올림에 도움을 줄 수.

  10. from https://stackoverflow.com/questions/17482623/rounding-to-2-decimal-places-using-mongodb-aggregation-framework by cc-by-sa and MIT license