2014-06-20 5 views
1

나는이 같은, 내가 몽고 집계 파이프 라인 내부에 사용하려는 JS 객체 norm 있습니다mongodb 집계 파이프 라인에서 Javascript 객체를 사용하는 방법은 무엇입니까?

var norm = { 
    1: 1, 
    2: 1.16, 
    3: 1.413, 
    4: 1.622, 
    5: 1.6, 
    6: 1.753, 
    7: 3.001, 
    8: 2.818, 
    9: 3.291, 
    10: 2.824, 
    11: 2.993, 
    12: 2.699, 
    13: 1.099, 
    14: 1.035, 
    15: 1.172, 
    16: 1.013, 
    17: 0.9936, 
    18: 1.069 
}; 

db.mycoll.aggregate([ 
    {$match : 
     {"_id.day" : ISODate("2014-06-19T00:00:00.000Z"), 
     "_id.lt" : "l", 
     "_id.rt" : "rltdlsts", 
     "_id.m": false } 
    }, 

    {$unwind: '$value.rl'}, 

    {$match: {'value.rl.p': {$gte: 1, $lte: 18} } }, 

    {$group: {_id: '$value.rl.a', 
       v: {$sum: '$value.rl.v'}, 
       nv: { $sum: { $multiply: [ norm['$value.rl.p'], '$value.rl.v' ] } }, 
       c: {$sum: '$value.rl.c'} 
      }}, 

    {$project: { 
     _id: "$_id", 
     'v': "$v", 
     'c': "$c", 
     'nv': "$nv" 
     } 
    }, 

    {$sort: {'_id': 1}} 
]) 

이 같은 결과를 얻을, nv은 항상 0입니다 :

{ 
    "result" : [ 
     { 
      "_id" : 1, 
      "v" : 89172, 
      "nv" : 0, 
      "c" : 604 
     }, 
     { 
      "_id" : 4, 
      "v" : 67872, 
      "nv" : 0, 
      "c" : 296 
     }, 
     { 
      "_id" : 5, 
      "v" : 33999, 
      "nv" : 0, 
      "c" : 13 
     }, 
     { 
      "_id" : 6, 
      "v" : 4727, 
      "nv" : 0, 
      "c" : 6 
     }, 
     { 
      "_id" : 8, 
      "v" : 913118, 
      "nv" : 0, 
      "c" : 14055 
     }, 
     { 
      "_id" : 9, 
      "v" : 204099, 
      "nv" : 0, 
      "c" : 3021 
     }, 
     { 
      "_id" : 11, 
      "v" : 151711, 
      "nv" : 0, 
      "c" : 1075 
     }, 
     { 
      "_id" : 12, 
      "v" : 196369, 
      "nv" : 0, 
      "c" : 601 
     }, 
     { 
      "_id" : 13, 
      "v" : 277705, 
      "nv" : 0, 
      "c" : 2302 
     }, 
     { 
      "_id" : 14, 
      "v" : 64005, 
      "nv" : 0, 
      "c" : 970 
     }, 
     { 
      "_id" : 15, 
      "v" : 54558, 
      "nv" : 0, 
      "c" : 326 
     }, 
     { 
      "_id" : 16, 
      "v" : 74576, 
      "nv" : 0, 
      "c" : 305 
     }, 
     { 
      "_id" : 17, 
      "v" : 1144, 
      "nv" : 0, 
      "c" : 1 
     }, 
     { 
      "_id" : 18, 
      "v" : 1023, 
      "nv" : 0, 
      "c" : 0 
     }, 
     { 
      "_id" : 19, 
      "v" : 54511, 
      "nv" : 0, 
      "c" : 98 
     }, 
     { 
      "_id" : 20, 
      "v" : 674, 
      "nv" : 0, 
      "c" : 0 
     }, 
     { 
      "_id" : 21, 
      "v" : 3359, 
      "nv" : 0, 
      "c" : 4 
     }, 
     { 
      "_id" : 22, 
      "v" : 496402, 
      "nv" : 0, 
      "c" : 3786 
     }, 
     { 
      "_id" : 23, 
      "v" : 293212, 
      "nv" : 0, 
      "c" : 1904 
     }, 
     { 
      "_id" : 24, 
      "v" : 764087, 
      "nv" : 0, 
      "c" : 8847 
     }, 
     { 
      "_id" : 25, 
      "v" : 291358, 
      "nv" : 0, 
      "c" : 7012 
     }, 
     { 
      "_id" : 28, 
      "v" : 2933, 
      "nv" : 0, 
      "c" : 27 
     } 
    ], 
    "ok" : 1 
} 

방법 이 문제를 해결하려면?

+1

파이프 라인이 한 번 평가 된 후 'norm'을 사용할 수없는 실행을 위해 서버로 전송되기 때문에 그렇게 할 수 없습니다. Map-Reduce가 가장 좋은 방법 일 것입니다. – JohnnyHK

+1

오른쪽, 당신이하는 일을 정확히 할 수는 없지만 '$ value.rl.p'의 값에 따라 올바른 승수를 사용하기 위해 조건식을 사용하여 집계 파이프 라인을 설정할 수 있습니다. 하지만 프로그래밍 방식으로 수행 할 수 있습니다. –

+0

Thx, @JohnnyHK MR이 내 출구 : – arun

답변

5

mapReduce를 사용하지 않고 집계 프레임 워크에서이 방법에 접근하는 데는 몇 가지 방법이 있습니다. 최근의 MongoDB 2.6 이상 버전에는 변수를 정의하고 배열을 처리하기 위해 $let$map을 사용하는 데 도움이되는 일부 연산자가 있습니다.

은 외부 선언은 다음과 같이 이러한 목적을 위해 더 나은 같습니다

var norm = [ 
    { "key": 1, "value": 1 }, 
    { "key": 2, "value": 1.16 }, 
    { "key": 3, "value": 1.413 }, 
    { "key": 4, "value": 1.622 }, 
    { "key": 5, "value": 1.6 }, 
    { "key": 6, "value": 1.753 }, 
    { "key": 7, "value": 3.001 }, 
    { "key": 8, "value": 2.818 }, 
    { "key": 9, "value": 3.291 }, 
    { "key": 10,"value": 2.824 }, 
    { "key": 11, "value": 2.993 }, 
    { "key": 12, "value": 2.699 }, 
    { "key": 13, "value": 1.099 }, 
    { "key": 14, "value": 1.035 }, 
    { "key": 15, "value": 1.172 }, 
    { "key": 16, "value": 1.013 }, 
    { "key": 17, "value": 0.9936 }, 
    { "key": 18, "value": 1.069 } 
]; 

을 그리고 집계 문 처리 : 당신이 실제로 배열로 외부 선언을 주입되는 $project 단계에서

db.mycoll.aggregate([ 
    { "$match": { 
     "_id.day" : ISODate("2014-06-19T00:00:00.000Z"), 
     "_id.lt" : "l", 
     "_id.rt" : "rltdlsts", 
     "_id.m": false 
    }}, 
    { "$unwind": "$value.rl" }, 

    { "$match": { "value.rl.p": { "$gte": 1, "$lte": 18 } } }, 

    { "$project": { 
     "value": 1, 
     "norm": { 
      "$let": { 
       "vars": { 
        "norm": norm 
       }, 
       "in": { 
        "$setDifference": [ 
         { "$map": { 
          "input": "$$norm", 
          "as": "norm", 
          "in": { 
           "$cond": [ 
            { "$eq": [ "$$norm.key", "$value.rl.p" ] }, 
            "$$norm.value", 
            false 
           ] 
          } 
         }}, 
         [false] 
        ] 
       } 
      }    
     } 
    }}, 
    { "$unwind": "$norm" } 

    { "$group": { 
     "_id": "$value.rl.a", 
     "v": { "$sum": "$value.rl.v" }, 
     "c": { "$sum": "$value.rl.c" }, 
     "nv": { "$sum": { "$multiply": [ "$norm", "$value.rl.v" ] } } 
    }} 
]) 

을 변수를 파이프 라인에 추가 한 다음 기존 "value.rl.p"키와 일치하도록 각 요소를 처리하십시오. 이것은 일치하는 단일 값만 반환하므로 $unwind을 사용하면 단일 요소 배열 결과가 나중에 $group 문에서 사용할 단일 값이됩니다.

연산자가 지원되지 않는 이전 버전의 전통적인 접근 방식은 각 값을 평가하기 위해 중첩 된 $cond 문을 사용하는 것입니다

db.mycoll.aggregate([ 
    { "$match": { 
     "_id.day" : ISODate("2014-06-19T00:00:00.000Z"), 
     "_id.lt" : "l", 
     "_id.rt" : "rltdlsts", 
     "_id.m": false 
    }}, 

    { "$unwind": "$value.rl" }, 

    { "$match": { "value.rl.p": { "$gte": 1, "$lte": 18 } } }, 

    { "$group": { 
     "_id": "$value.rl.a", 
     "v": { "$sum": "$value.rl.v" }, 
     "c": { "$sum": "$value.rl.c" }, 
     "nv": { "$sum": { "$multiply": [ 
      { "$cond": [ 
       { "$eq": [ "$value.rl.p", 2 }, 
       1.16 
       { "$cond": [ 
        { "$eq": [ "$value.rl.p", 3 }, 
        1.413, 
        { "$cond": [ 
         { "$eq": [ "$value.rl.p", 4 }, 
         1.622, 
         { "$cond": [ 
          { "$eq": [ "$value.rl.p", 5 }, 
          1.6, 
          { "$cond": [ 
           { "$eq": [ "$value.rl.p", 6 }, 
           1.753, 
           { "$cond": [ 
            { "$eq": [ "$value.rl.p", 7 }, 
            3.001, 
            { "$cond": [ 
             { "$eq": [ "$value.rl.p", 8 }, 
             2.818, 
             { "$cond": [ 
              { "$eq": [ "$value.rl.p", 9 }, 
              3.291, 
              { "$cond": [ 
               { "$eq": [ "$value.rl.p", 10 }, 
               2.824, 
               { "$cond": [ 
                { "$eq": [ "$value.rl.p", 11 }, 
                2.993, 
                { "$cond": [ 
                 { "$eq": [ "$value.rl.p", 12 }, 
                 2.699, 
                 { "$cond": [ 
                  { "$eq": [ "$value.rl.p", 13 }, 
                  1.099, 
                  { "$cond": [ 
                   { "$eq": [ "$value.rl.p", 14 }, 
                   1.035, 
                   { "$cond": [ 
                    { "$eq": [ "$value.rl.p", 15 }, 
                    1.172, 
                    { "$cond": [ 
                     { "$eq": [ "$value.rl.p", 16 }, 
                     1.013, 
                     { "$cond": [ 
                      { "$eq": [ "$value.rl.p", 17 }, 
                      0.9936, 
                      { "$cond": [ 
                       { "$eq": [ "$value.rl.p", 18 }, 
                       1.069, 
                       1 
                      ]} 
                     ]} 
                    ]} 
                   ]} 
                  ]} 
                 ]} 
                ]} 
               ]} 
              ]} 
             ]} 
            ]} 
           ]} 
          ]} 
         ]} 
        ]} 
       ]} 
      ]}, 
      "$value.rl.v" 
     ]}} 
    }} 
]) 

그것은 시끄러운 모양을하지만, 이전에 쿼리를 다음으로 가장 효율적인 형태이다 위에 표시된. 실제로 파이프 라인 단계를 생성하는 방법은 shown here과 비슷한 방법입니다.

+0

시끄 럽지만 인상적입니다. –

관련 문제