2016-07-07 3 views
0

MongoDB에서 일부 SQL 동작을 복제하는 방법에 대한 도움이 필요합니다.MongoDb 집계 (SQL UNION 스타일)

{ 
    "_id" : ObjectId("577ebc0660084921141a7857"), 
    "tournament" : "Wimbledon", 
    "player1" : "Agassi", 
    "player2" : "Lendl", 
    "sets" : [{ 
     "score1" : 6, 
     "score2" : 4, 
     "tiebreak" : false 
    }, { 
     "score1" : 7, 
     "score2" : 6, 
     "tiebreak" : true 
    }, { 
     "score1" : 7, 
     "score2" : 6, 
     "tiebreak" : true 
    }] 
} 
{ 
    "_id" : ObjectId("577ebc3560084921141a7858"), 
    "tournament" : "Wimbledon", 
    "player1" : "Ivanisevic", 
    "player2" : "McEnroe", 
    "sets" : [{ 
     "score1" : 4, 
     "score2" : 6, 
     "tiebreak" : false 
    }, { 
     "score1" : 3, 
     "score2" : 6, 
     "tiebreak" : false 
    }, { 
     "score1" : 6, 
     "score2" : 4, 
     "tiebreak" : false 
    }] 
} 
{ 
    "_id" : ObjectId("577ebc7560084921141a7859"), 
    "tournament" : "Roland Garros", 
    "player1" : "Navratilova", 
    "player2" : "Graf", 
    "sets" : [{ 
     "score1" : 5, 
     "score2" : 7, 
     "tiebreak" : false 
    }, { 
     "score1" : 6, 
     "score2" : 3, 
     "tiebreak" : false 
    }, { 
     "score1" : 7, 
     "score2" : 7, 
     "tiebreak" : true 
    }, { 
     "score1" : 7, 
     "score2" : 5, 
     "tiebreak" : false 
    }] 
} 

그리고이 두 가지 집계 : 특히,이 컬렉션을 부여

1) 집계 ALFA이 집계는이 모든 일치를 찾을 수 있도록 설계되어 있다는 점에서, 의도적으로 이상한입니다 적어도 하나의 tiebreak는 true입니다.하지만 은 tiebreak가 false 인 부분을 보여줍니다.. 그것의 논리를 고려하지 말라, 그것은 사용자에게 완전한 자유를 허용하도록 만들어진다.

{ 
    $match: { 
     "tournament": "Wimbledon", 
     "sets.tiebreak": true 
    } 
}, 
{ 
    $project: { 
     "tournament": 1, 
     "player1": 1, 
     "sets": { 
      $filter: { 
       input: "$sets", 
       as: "set", 
       cond: { 
        $eq: ["$$set.tiebreak", false] 
       } 
      } 
     } 
    } 
} 

2) 집계 베타이 집계가 적어도 1 타이 브레이크가 거짓하지만 타이 브레이크 사실이다 만 세트를 모두 표시 일치하는 항목을 찾을 수 있도록 설계되어 있다는 점에서, 의도적으로 이상하다 . 그것의 논리를 고려하지 말라, 그것은 사용자에게 완전한 자유를 허용하도록 만들어진다. player1이 결과에서 숨겨집니다.

{ 
    $match: { 
     "tournament": "Roland Garros", 
     "sets.tiebreak": false 
    } 
}, 
{ 
    $project: { 
     "tournament": 1, 
     "sets": { 
      $filter: { 
       input: "$sets", 
       as: "set", 
       cond: { 
        $eq: ["$$set.tiebreak", true] 
       } 
      } 
     } 
    } 
} 

지금이 두 가지 집계의 목적은 사용자가 두 쿼리는 사용자가 볼 수있는 모든 문서 (및 관련 정보)를 구분하는 의미에서 볼 수있는 데이터베이스의 어떤 부분 구분하는 것으로 가정합니다. 이는 사용자가 액세스 할 수있는 2 개의 SQL보기와 유사합니다.

이전의 고유 한 집계를 하나만 다시 작성해야합니다. 이것이 성취 될 수 있습니까?

은, 데이터에 대한 어떠한 제어를 잃지 않고

구체적 쿼리 A의 가능 또는 B. 아니라고 새어 데이터없이 취합 & B에 설정된 모든 제한을 유지하는 필수에 일치 윔블던은 적어도 하나의 결투가 끝난 경우에만 볼 수 있습니다. Player1 필드를 볼 수 있습니다. 단일 세트가 tiebreak로 끝나지 않으면 숨겨져 야합니다. 필요하다면 player1을 전혀 보지 않아도되지만 바람직하지는 않습니다.

반대로, Roland Garros의 경기는 최소한 하나의 세트가 동점 휴식없이 종료 된 경우에만 볼 수 있습니다. 플레이어 1 필드를 숨겨야합니다. 단일 세트는 tiebreak로 끝나고 그렇지 않으면 숨겨져 있어야합니다.

이 목적은 다시 두 집계에 의해 부과 된 제한을 유지하면서 두 집계를 결합하는 것입니다.

MongoDB는 버전 3.5이며, 필요한 경우 불안정한 릴리스로 업그레이드 할 수 있습니다.

+0

텍스트 필터에서 정규 표현식을 사용하는 것이 추가로 필요합니다. 성과 중심 전략은 필수 사항은 아니지만 더하기입니다. – Manuele

+0

그것은 하나의 컬렉션에서 데이터를 가져 오는 것으로 보입니다. 따라서 두 가지 유형의 데이터 모두를 얻으려면 $ 또는를 사용하십시오. UNION은 일반적으로 비슷한 열이있는 여러 테이블에서 가져옵니다. – Tiramisu

+0

네, 같은 콜렉션에서 가져 왔습니다 ...하지만 불행히도 요점은 $ match stage ($ 또는 ... 사용)가 아니라 불가능한/너무 어려운 $ project 단계입니다 ... 감사합니다 어쨌든! – Manuele

답변

0

여기에 문제에 대한 내 두 센트 : 당신이

  • 는 "윔블던"문서가 모든true tibreaks가있을 때 빈 세트를 방지하고자하는 경우,
  • 또는 "롤랑 "은 모두false tiebreaks

당신은 쿼리를 바꿀 수 있습니다

... 
{ 
    $and: [{ 
    "sets.tiebreak": true, 
    }, { 
    "sets.tiebreak": false 
    }], 
    $or: [{ 
    "tournament": "Wimbledon" 
    }, { 
    "tournament": "Roland Garros" 
    }] 
} 
... 

을하고 그것을 사용 http://pastebin.com/MShihSQL (성능이 더 큰 문제가 ..가없는 경우)

+0

이것은 단지 테스트 였기 때문에 어느 것이 올바른 행동인지 알기가 어렵습니다. 요점은 SQL UNION을 모방하는 것이 었습니다. "Aggregation ALFA/BETA"가 빈 세트를 반환 할 것이므로, * 내 쿼리가 여전히 가장 정확하다고 생각하지만, 주석이 올바른 주석 이상을 가리키고 있다고 생각합니다. 두 가지 접근 방식을 벤치마킹하는 것이 좋습니다. 더 많은 단계 = 더 많은 시간이 걸릴 것으로 생각하지만, 하드/투사가 성냥/풀림/성냥 목록보다 더 많은 시간을 소비 할 수도 있습니다. 조사 할 것입니다 ... – Manuele

+0

나는 당신의 답을 이전의 논평에서 이유를 정정해라. 그러나 그것은 분명히 유효한 접근법이다. – Manuele