bottomN(์ง๊ณ ๋์ฐ๊ธฐ)
์ด ํ์ด์ง์ ๋ด์ฉ
์ ์
๊ตฌ๋ฌธ
{ $bottomN: { n: <expression>, sortBy: { <field1>: <sort order>, <field2>: <sort order> ... }, output: <expression> } }
n
์ ๊ทธ๋ฃน๋น ๊ฒฐ๊ณผ ์๋ฅผ ์ ํํ๋ฉฐ$group
์_id
๊ฐ์ ์์กดํ๊ฑฐ๋ ์์์ธ ์์ ์ ์ ํํ์์ด์ด์ผ ํฉ๋๋ค
sortBy๋
$sort
์ ์ ์ฌํ ๊ตฌ๋ฌธ์ ์ฌ์ฉํ์ฌ ๊ฒฐ๊ณผ์ ์์๋ฅผ ์ง์ ํฉ๋๋ค.output
์ ๊ทธ๋ฃน ์ ๊ฐ ์์์ ๋ํ ์ถ๋ ฅ์ ๋ํ๋ด๋ฉฐ ๋ชจ๋ ํํ์ ์ด ๋ ์ ์์ต๋๋ค.
ํ๋
Null ๋ฐ ๋๋ฝ๋ ๊ฐ
$bottomN
์ null ๊ฐ์ ํํฐํ๋ค ํ์ง ์์ต๋๋ค.$bottomN
์ ๋๋ฝ๋ ๊ฐ์ ์ถ๋ ฅ์ ๋ณด์กด๋๋ 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: { $bottomN: { output: [ "$playerId", "$score" ], sortBy: { "score": -1 }, n: 3 } } } } ] )
์ด ์์์์๋
$documents
๋ ํ๋ ์ด์ด ์ ์๊ฐ ํฌํจ๋ ๋ฆฌํฐ๋ด ๋ฌธ์๋ฅผ ์์ฑํฉ๋๋ค.$group
์gameId
๊ธฐ์ค์ผ๋ก ๋ฌธ์๋ฅผ ๊ทธ๋ฃนํํฉ๋๋ค. ์ด ์์์๋gameId
๊ฐ ๋จ ํ๋(G1
)๋ง ์์ต๋๋ค.PlayerD
์๋ ๋๋ฝ๋ ์ ์๊ฐ ์๊ณPlayerE
์๋ nullscore
์ด(๊ฐ) ์์ต๋๋ค. ์ด ๊ฐ์ ๋ชจ๋ 'null'๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.playerId
๋ฐscore
ํ๋๋output : ["$playerId"," $score"]
๋ก ์ง์ ๋๊ณ ๋ฐฐ์ด ๊ฐ์ผ๋ก ๋ฐํ๋ฉ๋๋ค.sortBy: { "score" : -1 }
๋๋ฌธ์ null ๊ฐ์ ๋ฐํ๋playerId
๋ฐฐ์ด์ ๋์ผ๋ก ์ ๋ ฌ๋ฉ๋๋ค.
[ { _id: "G1", playerId: [ [ "PlayerA", 1 ], [ "PlayerD", null ], [ "PlayerE", null ] ] } ]
BSON ๋ฐ์ดํฐ ์ ํ ์ ๋ ฌ ์์
์๋ก ๋ค๋ฅธ ์ ํ์ ์ ๋ ฌํ ๋ 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: { $bottomN: { output: ["$playerId","$score"], sortBy: {"score": -1}, n: 3 } } } } ] )
์ด ์์์์๋
PlayerA
์๋ ์ ์ ์ ์๊ฐ ์์ต๋๋ค.PlayerB
์ ๋ฌธ์์ด"2"
์ ์๊ฐ ์์ต๋๋ค.PlayerC
์ ๋น string ์ ์๊ฐ ์์ต๋๋ค.
์ ๋ ฌ์ด { "score" : -1 }
๋ด๋ฆผ์ฐจ์์ผ๋ก ์ด๋ฃจ์ด์ง๊ธฐ ๋๋ฌธ์ ๋ฌธ์์ด ๋ฆฌํฐ๋ด ๊ฐ์ PlayerA
์ ์ซ์ ์ ์๋ณด๋ค ๋จผ์ ์ ๋ ฌ๋ฉ๋๋ค.
[ { _id: "G1", playerId: [ [ "PlayerB", "2" ], [ "PlayerC", "" ], [ "PlayerA", 1 ] ] } ]
์ ํ ์ฌํญ
์ฐฝ ํจ์ ๋ฐ ์ง๊ณ ํํ์ ์ง์
$bottomN
์(๋) ์ง๊ณ ํํ์์ผ๋ก ์ง์๋์ง ์์ต๋๋ค.
$bottomN
์(๋) window operator
(์ผ)๋ก ์ง์๋ฉ๋๋ค.
๋ฉ๋ชจ๋ฆฌ ์ ํ ๊ณ ๋ ค ์ฌํญ
$bottomN
์ง๊ณ ํ์ดํ๋ผ์ธ ๋ด์ ๊ทธ๋ฃน์๋ 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 } ])
๊ฐ์ฅ ๋ฎ์ {03}๊ฐ ์ฐพ๊ธฐ
$bottomN
์ถ์ ์๋ฅผ ์ฌ์ฉํ์ฌ ๋จ์ผ ๊ฒ์์์ ๊ฐ์ฅ ๋ฎ์ ์ ์๋ฅผ ๋ฐ์ ํ๋ ์ด์ด๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค.
db.gamescores.aggregate( [ { $match : { gameId : "G1" } }, { $group: { _id: "$gameId", playerId: { $bottomN: { output: ["$playerId", "$score"], sortBy: { "score": -1 }, n:3 } } } } ] )
์์ ํ์ดํ๋ผ์ธ:
$match
๋ฅผ ์ฌ์ฉํ์ฌ ๋จ์ผgameId
๊ฒฐ๊ณผ๋ฅผ ํํฐ๋งํฉ๋๋ค. ์ด ๊ฒฝ์ฐ์๋G1
์ ๋๋ค.$group
์ ์ฌ์ฉํ์ฌgameId
๋ฅผ ๊ธฐ์ค์ผ๋ก ๊ฒฐ๊ณผ๋ฅผ ๊ทธ๋ฃนํํฉ๋๋ค. ์ด ๊ฒฝ์ฐ์๋G1
์ ๋๋ค.{ "score": -1 }
๊ธฐ์ค ์ ๋ ฌ์ ์ฌ์ฉํ์ฌ ๊ฒฐ๊ณผ๋ฅผ ๋ด๋ฆผ์ฐจ์์ผ๋ก ์ ๋ ฌํฉ๋๋ค.$bottomN
์์output : ["$playerId"," $score"]
๋ก ์ถ๋ ฅ๋๋ ํ๋๋ฅผ ์ง์ ํฉ๋๋ค.$bottomN
์ ์ฌ์ฉํ์ฌn : 3
๊ฐ ์๋G1
๊ฒ์์์ ๊ฐ์ฅ ๋ฎ์score
๋ฅผ ๊ฐ์ง ํ์ ์ธ ๋ฌธ์๋ฅผ ๋ฐํํฉ๋๋ค.
์ด ์ฐ์ฐ์ ๋ค์๊ณผ ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํฉ๋๋ค.
[ { _id: "G1", playerId: [ [ "PlayerB", 33 ], [ "PlayerA", 31 ], [ "PlayerD", 1 ] ] } ]
์ด ์ฟผ๋ฆฌ์ ๋์ผํ 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) AS T3 ON GS.GAMEID = T3.GAMEID GROUP BY T3.GAMEID,T3.PLAYERID,T3.SCORE ORDER BY T3.SCORE DESC
์ฌ๋ฌ ๊ฒ์์์ ์ ์๊ฐ ๊ฐ์ฅ ๋ฎ์ ๋ฌธ์ 3๊ฐ ์ฐพ๊ธฐ
$bottomN
์ถ์ ์๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ ๊ฒ์์์ ๊ฐ์ฅ ๋ฎ์ ์ ์๋ฅผ ๋ฐ์ ํ๋ ์ด์ด๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค.
db.gamescores.aggregate( [ { $group: { _id: "$gameId", playerId: { $bottomN: { output: [ "$playerId","$score" ], sortBy: { "score": -1 }, n: 3 } } } } ] )
์์ ํ์ดํ๋ผ์ธ:
$group
์ ์ฌ์ฉํ์ฌgameId
๋ฅผ ๊ธฐ์ค์ผ๋ก ๊ฒฐ๊ณผ๋ฅผ ๊ทธ๋ฃนํํฉ๋๋ค.$bottomN
์์output : ["$playerId", "$score"]
๋ก ์ถ๋ ฅ๋๋ ํ๋๋ฅผ ์ง์ ํฉ๋๋ค.{ "score": -1 }
๊ธฐ์ค ์ ๋ ฌ์ ์ฌ์ฉํ์ฌ ๊ฒฐ๊ณผ๋ฅผ ๋ด๋ฆผ์ฐจ์์ผ๋ก ์ ๋ ฌํฉ๋๋ค.$bottomN
์ ์ฌ์ฉํ์ฌ ๊ฐ ๊ฒ์์์ ๊ฐ์ฅ ๋ฎ์score
๋ฅผ ๊ฐ์ง ํ์ ์ธ ๋ฌธ์๋ฅผn: 3
๋ก ๋ฐํํฉ๋๋ค.
์ด ์ฐ์ฐ์ ๋ค์๊ณผ ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํฉ๋๋ค.
[ { _id: "G1", playerId: [ [ "PlayerB", 33 ], [ "PlayerA", 31 ], [ "PlayerD", 1 ] ] }, { _id: "G2", playerId: [ [ "PlayerC", 66 ], [ "PlayerB", 14 ], [ "PlayerA", 10 ] ] } ]
์ด ์ฟผ๋ฆฌ์ ๋์ผํ 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 >= 2 ORDER BY GAMEID
$group
์ ๊ทธ๋ฃน ํค๋ฅผ ๊ธฐ๋ฐ์ผ๋ก n
๊ณ์ฐ
n
์ ๊ฐ์ ๋์ ์ผ๋ก ํ ๋นํ ์๋ ์์ต๋๋ค. ์ด ์์ ์์๋ $cond
ํํ์์ด gameId
ํ๋์ ์ฌ์ฉ๋ฉ๋๋ค.
db.gamescores.aggregate([ { $group: { _id: {"gameId": "$gameId"}, gamescores: { $bottomN: { output: "$score", n: { $cond: { if: {$eq: ["$gameId","G2"] }, then: 1, else: 3 } }, sortBy: { "score": -1 } } } } } ] )
์์ ํ์ดํ๋ผ์ธ:
$group
์ ์ฌ์ฉํ์ฌgameId
์ ๊ธฐ์ค์ผ๋ก ๊ฒฐ๊ณผ๋ฅผ ๊ทธ๋ฃนํํฉ๋๋ค.$bottomN
์์output : "$score"
๋ก ์ถ๋ ฅ๋๋ ํ๋๋ฅผ ์ง์ ํฉ๋๋ค.gameId
๊ฐG2
์ด๋ฉดn
๋ 1์ด๊ณ , ๊ทธ๋ ์ง ์์ผ๋ฉดn
๋ 3์ ๋๋ค.{ "score": -1 }
๊ธฐ์ค ์ ๋ ฌ์ ์ฌ์ฉํ์ฌ ๊ฒฐ๊ณผ๋ฅผ ๋ด๋ฆผ์ฐจ์์ผ๋ก ์ ๋ ฌํฉ๋๋ค.
์ด ์ฐ์ฐ์ ๋ค์๊ณผ ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํฉ๋๋ค.
[ { _id: { gameId: "G2" }, gamescores: [ 10 ] }, { _id: { gameId: "G1" }, gamescores: [ 33, 31, 1 ] } ]