복붙노트

[MONGODB] MongoDB의 통합 프레임 워크의 경우 문을 수행

MONGODB

MongoDB의 통합 프레임 워크의 경우 문을 수행

나는 우리가 현재 SQL 서버의 상단에서 실행되는 것처럼 MongoDB의 통합 프레임 워크는 우리의 요구에 맞는 얼마나 잘 평가하고 있습니다. 나는 특정 쿼리를 수행하는 힘든 시간을 보내고 있습니다 :

나는 다음과 같은 의사의 기록을 말해봐 (SQL 테이블의 열으로 모델링을하고, MongoDB의 컬렉션에서 전체 문서로)

{
   name: 'A',
   timespent: 100,
},
{
   name: 'B',
   timespent: 200,
},
{
   name: 'C',
   timespent: 300,
},
{
   name: 'D',
   timespent: 400,
},
{
   name: 'E',
   timespent: 500,
}

나는 범위에 그룹에 timespent 필드를 원하고 내가 얻을 수 있도록 발생을 계산 예를 들어, 다음 의사 기록 :

results{
   0-250: 2,
   250-450: 2,
   450-650: 1
}

이 범위 (250, 450, 650)는 동적이며 아마도 사용자에 의해 시간이 지남에 따라 변경 될 것을 유의해야한다. SQL에서 우리는 이런 일에 결과를 추출 :

select range, COUNT(*) as total from (
select case when Timespent <= 250 then '0-250'
when Timespent <= 450 then '200-450'
else '450-600' end as range
from TestTable) as r
group by r.range

다시 말하지만,이 SQL은 특정에 맞게 우리의 응용 프로그램에 의해 동적으로 생성되는 노트는 하나의 시점에서 사용 가능한 범위.

나는 MongoDB의 통합 프레임 워크에 적절한 구조는 쿼리를 수행하기 위해 찾기 위해 사투를 벌인거야. 나는 (즉. 단일 범위의 결과를 얻는) 파이프 라인에 $ 일치를 삽입하여 단일 범위의 결과를 조회 할 수 있습니다하지만 난 하나의 파이프 라인 쿼리의 범위와 그 카운트를 모두 추출하는 방법을 grok 수 없습니다.

해결법

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

    1.집계 프레임 워크의 "사건"SQL 문에 해당하는 무엇은 $ COND 연산자 (매뉴얼 참조). $ COND 문이 "다른" "때-다음"시뮬레이션하고 중첩 될 수 있지만, 쉽게 읽을 수 있기 때문에 나는 다른 방법을 선택했다 (그리고 생성하기 위해, 아래 참조) : 내가 쓰기에 $의 CONCAT 연산자를 사용합니다 다음 키를 그룹화 역할 범위 문자열.

    집계 프레임 워크의 "사건"SQL 문에 해당하는 무엇은 $ COND 연산자 (매뉴얼 참조). $ COND 문이 "다른" "때-다음"시뮬레이션하고 중첩 될 수 있지만, 쉽게 읽을 수 있기 때문에 나는 다른 방법을 선택했다 (그리고 생성하기 위해, 아래 참조) : 내가 쓰기에 $의 CONCAT 연산자를 사용합니다 다음 키를 그룹화 역할 범위 문자열.

    지정된 컬렉션에 대한 그래서 :

    db.xx.find()
    { "_id" : ObjectId("514919fb23700b41723f94dc"), "name" : "A", "timespent" : 100 }
    { "_id" : ObjectId("514919fb23700b41723f94dd"), "name" : "B", "timespent" : 200 }
    { "_id" : ObjectId("514919fb23700b41723f94de"), "name" : "C", "timespent" : 300 }
    { "_id" : ObjectId("514919fb23700b41723f94df"), "name" : "D", "timespent" : 400 }
    { "_id" : ObjectId("514919fb23700b41723f94e0"), "name" : "E", "timespent" : 500 }
    

    집계는 (하드 코딩) 다음과 같습니다 :

    db.xx.aggregate([
      { $project: {
        "_id": 0,
        "range": {
          $concat: [{
            $cond: [ { $lte: ["$timespent", 250] }, "range 0-250", "" ]
          }, {
            $cond: [ { $and: [
              { $gte: ["$timespent", 251] }, 
              { $lt:  ["$timespent", 450] } 
            ] }, "range 251-450", "" ]
          }, {
            $cond: [ { $and: [
              { $gte: ["$timespent", 451] }, 
              { $lt:  ["$timespent", 650] } 
            ] }, "range 450-650", "" ]
          }]
        }
      }},
      { $group: { _id: "$range", count: { $sum: 1 } } },
      { $sort: { "_id": 1 } },
    ]);
    

    그 결과는 다음과 같습니다

    {
        "result" : [
            {
                "_id" : "range 0-250",
                "count" : 2
            },
            {
                "_id" : "range 251-450",
                "count" : 2
            },
            {
                "_id" : "range 450-650",
                "count" : 1
            }
        ],
        "ok" : 1
    }
    

    집계 명령을 생성하기 위해, 당신은 JSON 개체로 "범위"투사를 구축해야 (또는 문자열을 생성하고 JSON.parse을 사용할 수 있습니다 (문자열))

    발전기는 다음과 같습니다 :

    var ranges = [ 0, 250, 450, 650 ];
    var rangeProj = {
      "$concat": []
    };
    
    for (i = 1; i < ranges.length; i++) {
      rangeProj.$concat.push({
        $cond: {
          if: {
            $and: [{
              $gte: [ "$timespent", ranges[i-1] ]
            }, {
              $lt: [ "$timespent", ranges[i] ]
            }]
          },
          then: "range " + ranges[i-1] + "-" + ranges[i],
          else: ""
        }
      })
    }
    
    db.xx.aggregate([{
      $project: { "_id": 0, "range": rangeProj }
    }, {
      $group: { _id: "$range", count: { $sum: 1 } }
    }, {
      $sort: { "_id": 1 }
    }]);
    

    이는 상기와 같은 결과를 반환한다.

  2. ==============================

    2.MongoDB를 3.4에서 시작하여 우리는 $ 프로젝트 단계에서 멀티 스위치 문을 수행하기 위해 $ 스위치 연산자를 사용할 수 있습니다.

    MongoDB를 3.4에서 시작하여 우리는 $ 프로젝트 단계에서 멀티 스위치 문을 수행하기 위해 $ 스위치 연산자를 사용할 수 있습니다.

    하여 $ 기 파이프 라인 연산자 기 "범위"의 $ 합계 누산기 연산자를 사용하여 각 그룹의 "수"를 반환하여 문서.

    db.collection.aggregate(
        [  
            { "$project": { 
                "range": { 
                    "$switch": { 
                        "branches": [ 
                            { 
                                "case": { "$lte": [ "$timespent", 250 ] }, 
                                "then": "0-250" 
                            }, 
                            { 
                                "case": { 
                                    "$and": [ 
                                        { "$gt": [ "$timespent", 250 ] }, 
                                        { "$lte": [ "$timespent", 450 ] } 
                                    ] 
                                }, 
                                "then": "251-450" 
                            }, 
                            { 
                                "case": { 
                                    "$and": [ 
                                        { "$gt": [ "$timespent", 450 ] }, 
                                        { "$lte": [ "$timespent", 650 ] } 
                                    ] 
                                }, 
                                "then": "451-650" 
                            } 
                        ], 
                        "default": "650+" 
                    } 
                } 
            }}, 
            { "$group": { 
                "_id": "$range", 
                "count": { "$sum": 1 } 
            }}
        ]
    )
    

    우리의 컬렉션에서 다음 문서로,

    { "_id" : ObjectId("514919fb23700b41723f94dc"), "name" : "A", "timespent" : 100 },
    { "_id" : ObjectId("514919fb23700b41723f94dd"), "name" : "B", "timespent" : 200 },
    { "_id" : ObjectId("514919fb23700b41723f94de"), "name" : "C", "timespent" : 300 },
    { "_id" : ObjectId("514919fb23700b41723f94df"), "name" : "D", "timespent" : 400 },
    { "_id" : ObjectId("514919fb23700b41723f94e0"), "name" : "E", "timespent" : 500 }
    

    우리 쿼리 수율 :

    { "_id" : "451-650", "count" : 1 }
    { "_id" : "251-450", "count" : 2 }
    { "_id" : "0-250", "count" : 2 }
    

    우리는 종류의 파이프 라인 범위에 의해 우리의 문서에 $ 정렬 단계를 추가 할 수 있지만,이 때문에 "범위"의 종류의 사전 식 순서 만 종류의 문서 것이다.

  3. from https://stackoverflow.com/questions/15494113/performing-case-statement-in-mongodb-aggregation-framework by cc-by-sa and MIT license