Docs Menu
Docs Home
/
MongoDB 매뉴얼
/ / /

topN(집계 누산기)

이 페이지의 내용

  • 정의
  • 구문
  • 행동
  • 제한 사항
  • 예시
$topN

버전 5.2에 추가되었습니다.

지정된 정렬 순서에 따라 그룹 내 상위 n개 요소의 집계를 반환합니다. 그룹에 n개 미만의 요소가 포함된 경우 $topN은 그룹의 모든 요소를 반환합니다.

{
$topN:
{
n: <expression>,
sortBy: { <field1>: <sort order>, <field2>: <sort order> ... },
output: <expression>
}
}
  • n 그룹 결과 수를 제한하며 $group에 대한 상수 또는 _id 값에 의존하는 양의 정수 표현식 이어야 합니다.

  • sortBy는 $sort 와 유사한 구문을 사용하여 결과의 순서를 지정합니다.

  • output 그룹의 각 요소에 대한 출력을 나타내며 모든 표현식이 될 수 있습니다.

  • $topN null 값을 필터링하지 않습니다.

  • $topN 누락된 값을 출력에 유지되는 null로 변환합니다.

db.aggregate( [
{
$documents: [
{ playerId: "PlayerA", gameId: "G1", score: 1 },
{ playerId: "PlayerB", gameId: "G1", score: 2 },
{ playerId: "PlayerC", gameId: "G1", score: 3 },
{ playerId: "PlayerD", gameId: "G1"},
{ playerId: "PlayerE", gameId: "G1", score: null }
]
},
{
$group:
{
_id: "$gameId",
playerId:
{
$topN:
{
output: [ "$playerId", "$score" ],
sortBy: { "score": 1 },
n: 3
}
}
}
}
] )

이 예시에서는

  • $documents 플레이어 점수가 포함된 리터럴 문서를 생성합니다.

  • $groupgameId 기준으로 문서를 그룹화합니다. 이 예시에는 gameId가 단 하나(G1)만 있습니다.

  • PlayerD 점수가 누락되었고 PlayerE에 null score가 있습니다. 이 값은 모두 null로 간주됩니다.

  • playerIdscore 필드는 output : ["$playerId"," $score"]로 지정되고 배열 값으로 반환됩니다.

  • sortBy: { "score" : 1 } 때문에 null 값은 반환된 playerId 배열 앞에 정렬됩니다.

[
{
_id: 'G1',
playerId: [ [ 'PlayerD', null ], [ 'PlayerE', null ], [ 'PlayerA', 1 ] ]
}
]

서로 다른 유형을 정렬할 때 BSON 데이터 유형 의 순서를 사용하여 순서를 결정합니다. 예를 들어 값이 문자열과 숫자로 구성된 컬렉션을 생각해 보겠습니다.

  • 오름차순 정렬에서는 문자열 값이 숫자 값 뒤에 정렬됩니다.

  • 내림차순 정렬에서는 문자열 값이 숫자 값보다 먼저 정렬됩니다.

db.aggregate( [
{
$documents: [
{ playerId: "PlayerA", gameId: "G1", score: 1 },
{ playerId: "PlayerB", gameId: "G1", score: "2" },
{ playerId: "PlayerC", gameId: "G1", score: "" }
]
},
{
$group:
{
_id: "$gameId",
playerId: {
$topN:
{
output: ["$playerId","$score"],
sortBy: {"score": -1},
n: 3
}
}
}
}
] )

이 예시에서는

  • PlayerA 의 점수는 정수입니다.

  • PlayerB 문자열 "2" 점수를 가집니다.

  • PlayerC 빈 문자열 점수가 있습니다.

정렬이 { "score" : -1 } 내림차순으로 이루어지기 때문에 문자열 리터럴 값은 PlayerA 의 숫자 점수보다 먼저 정렬됩니다.

[
{
_id: "G1",
playerId: [ [ "PlayerB", "2" ], [ "PlayerC", "" ], [ "PlayerA", 1 ] ]
}
]

$topN 집계 표현식으로 지원되지 않습니다.

$topNwindow operator로 지원됩니다.

$topN 집계 파이프라인 내의 그룹에는 100MB 제한 파이프라인 제한이 적용됩니다. 개별 그룹에 대해 이 제한을 초과하면 오류가 발생하면서 애그리게이션이 실패합니다.

다음 문서가 포함된 gamescores collection을 생각해 보세요.

db.gamescores.insertMany([
{ playerId: "PlayerA", gameId: "G1", score: 31 },
{ playerId: "PlayerB", gameId: "G1", score: 33 },
{ playerId: "PlayerC", gameId: "G1", score: 99 },
{ playerId: "PlayerD", gameId: "G1", score: 1 },
{ playerId: "PlayerA", gameId: "G2", score: 10 },
{ playerId: "PlayerB", gameId: "G2", score: 14 },
{ playerId: "PlayerC", gameId: "G2", score: 66 },
{ playerId: "PlayerD", gameId: "G2", score: 80 }
])

$topN 축적자를 사용하여 단일 게임에서 가장 높은 점수를 획득한 플레이어를 찾을 수 있습니다.

db.gamescores.aggregate( [
{
$match : { gameId : "G1" }
},
{
$group:
{
_id: "$gameId",
playerId:
{
$topN:
{
output: ["$playerId", "$score"],
sortBy: { "score": -1 },
n:3
}
}
}
}
] )

예시 파이프라인:

  • $match를 사용하여 단일 gameId 결과를 필터링합니다. 이 경우에는 G1입니다.

  • $group을 사용하여 gameId를 기준으로 결과를 그룹화합니다. 이 경우에는 G1입니다.

  • { "score": -1 } 기준 정렬을 사용하여 결과를 내림차순으로 정렬합니다.

  • $topN 에서 output : ["$playerId"," $score"] 로 출력되는 필드를 지정합니다.

  • $topN을 사용하여 n : 3으로 G1 게임에서 가장 높은 score를 가진 상위 3개의 문서를 반환합니다.

이 연산은 다음과 같은 결과를 반환합니다.

[
{
_id: 'G1',
playerId: [ [ 'PlayerC', 99 ], [ 'PlayerB', 33 ], [ 'PlayerA', 31 ] ]
}
]

이 쿼리와 동일한 SQL:

SELECT T3.GAMEID,T3.PLAYERID,T3.SCORE
FROM GAMESCORES AS GS
JOIN (SELECT TOP 3
GAMEID,PLAYERID,SCORE
FROM GAMESCORES
WHERE GAMEID = 'G1'
ORDER BY SCORE DESC) AS T3
ON GS.GAMEID = T3.GAMEID
GROUP BY T3.GAMEID,T3.PLAYERID,T3.SCORE
ORDER BY T3.SCORE DESC

$topN 축적자를 사용하여 각 게임에서 가장 높은 점수를 받은 플레이어를 찾을 수 있습니다.

db.gamescores.aggregate( [
{
$group:
{ _id: "$gameId", playerId:
{
$topN:
{
output: [ "$playerId","$score" ],
sortBy: { "score": -1 },
n: 3
}
}
}
}
] )

예시 파이프라인:

  • $group을 사용하여 gameId를 기준으로 결과를 그룹화합니다.

  • $topN 에서 output : ["$playerId", "$score"] 로 출력되는 필드를 지정합니다.

  • { "score": -1 } 기준 정렬을 사용하여 결과를 내림차순으로 정렬합니다.

  • $topN을 사용하여 n: 3으로 각 게임에 대해 가장 높은 score를 가진 상위 3개의 문서를 반환합니다.

이 연산은 다음과 같은 결과를 반환합니다.

[
{
_id: 'G1',
playerId: [ [ 'PlayerC', 99 ], [ 'PlayerB', 33 ], [ 'PlayerA', 31 ] ]
},
{
_id: 'G2',
playerId: [ [ 'PlayerD', 80 ], [ 'PlayerC', 66 ], [ 'PlayerB', 14 ] ]
}
]

이 쿼리와 동일한 SQL:

SELECT PLAYERID,GAMEID,SCORE
FROM(
SELECT ROW_NUMBER() OVER (PARTITION BY GAMEID ORDER BY SCORE DESC) AS GAMERANK,
GAMEID,PLAYERID,SCORE
FROM GAMESCORES
) AS T
WHERE GAMERANK <= 3
ORDER BY GAMEID

n 의 값을 동적으로 할당할 수도 있습니다. 이 예제에서는 $cond 표현식이 gameId 필드에 사용됩니다.

db.gamescores.aggregate([
{
$group:
{
_id: {"gameId": "$gameId"},
gamescores:
{
$topN:
{
output: "$score",
n: { $cond: { if: {$eq: ["$gameId","G2"] }, then: 1, else: 3 } },
sortBy: { "score": -1 }
}
}
}
}
] )

예시 파이프라인:

  • $group을 사용하여 gameId를 기준으로 결과를 그룹화합니다.

  • $topN 에서 output : "$score" 로 출력되는 필드를 지정합니다.

  • gameIdG2 이면 n 는 1이고, 그렇지 않으면 n 는 3입니다.

  • { "score": -1 } 기준 정렬을 사용하여 결과를 내림차순으로 정렬합니다.

이 연산은 다음과 같은 결과를 반환합니다.

[
{ _id: { gameId: 'G1' }, gamescores: [ 99, 33, 31 ] },
{ _id: { gameId: 'G2' }, gamescores: [ 80 ] }
]

돌아가기

$top